Compare commits
No files matched your search
@@ -1,10 +1,393 @@
|
||||
# Changelog
|
||||
|
||||
## 未发布
|
||||
## 1.1.0
|
||||
|
||||
市场与洗钱的平衡调整:Poinbase 改为订单簿、DEX 稳定币对改为稳定币池、保险基金和爆仓新闻、预测市场流动性、收黑币、浏览器记录钱包的每一笔进出。存档兼容,读旧存档时自动升级。
|
||||
|
||||
- Poinbase 现货改为订单簿:价格只取决于当天的累计净买入量,价格 = 参考价 × exp(1.54 × |净买入名义 / 深度|^0.8),冲击随单子变大而增长得比线性慢;拆单不占便宜,同量买进再卖出回到原价。第 38 天买 2 PSC 的平均滑点约 0.1%(原来约 0.24%),卖 200 PSC 约 4%(原来约 21%)。基础深度 50,000 → 600,000,DEX 侧池仍是恒定乘积池,按比例跟着变深;现货与出金手续费 0.2% → 0.1%。NPC 大户每笔 2,000–8,000 → 24,000–96,000,对价格的影响和原来相近。
|
||||
- Poinbase 只上架 PSC、CRC、SPARK:作为合规交易所不收黑市的 CRT 和革命军的 CRA,往充值地址转这两种币时钱包拦下(“Poinbase 不收 CRT。”);资金页入金只列这三种,出金另外列出账户里还有余额的其他币(旧存档里已经充进来的)。现货新增 SPARK/CRC 订单簿(深度为主池的一半),行情图只有 PSC、SPARK、CRC,右边的交易对跟着选中的币切换。交易对一行不再写“(Poinbase)”,互换预览的损耗显示两位小数。
|
||||
- DEX 稳定币对(CRT/CRC、CRA/CRC)改为 StableSwap 池(Curve 的曲线):手续费 0.3% → 0.04%(参考 Curve 3pool;Uniswap v3 稳定币对用 0.01% / 0.05% 档),放大系数 200,挂钩附近几乎没有滑点。第 38 天 998 CRT 换 CRC 损耗 0.041%(1.0.0 约 4%),5 万约 0.08%;998 CRT 换 PSC 约 0.68%(PSC 池那一跳)。参考价偏离挂钩超过 1% 为脱锚,放大系数降到 20(脱锚到 0.92 时卖 5 万约 0.44%);超过 15% 为崩盘,放大系数 1、深度只剩四分之一(CRA 跌到 0.3 时卖 5 万约 8.7%)。脱锚幅度参考 USDC 2023 年 3 月(最低约 0.87,两三天回到 1)。
|
||||
- 永续的成交深度单独计算,基数 50,000 → 100,000,滑点减半(perpsim:均值回归策略 3,000 本金 120 天 4,261 → 5,467)。
|
||||
- Poinbase 交易界面:买入和卖出都输入标的币数量,标签“数量(PSC)”;买入预览改为“约需 X CRC”;交易对一行显示手续费;均价含手续费,滑点不含手续费。
|
||||
- 保险基金:初值 10,000 → 200,000(约 20 天的全网产出)。去掉“每晚固定补 150、NPC 大行情按冲击平方扣”的旧规则,改为 NPC 仓位随行情爆仓:亏损一侧的持仓为现货池深的 1 倍(SPARK 再乘 0.15),涨跌幅达到 25% 全部爆仓,之前按比例;大部分正常爆仓,剩下的保证金(名义价值的 0.5%)进基金;涨跌超过 12% 后穿仓的比例开始上升(5% 起,每多 1% 加 1.5%),缺口由基金垫付。离线模拟(300 局 × 200 天,带插针、事件、SPARK):基金缓慢上升,没有一局见底,最坏的单晚流出约 17 万。
|
||||
- 爆仓新闻:标记价单日涨跌达到 15% 时,报纸报道全网爆仓的人数和金额(含玩家被强平的仓位)以及保险基金余额;模拟里平均 10 天左右一次。
|
||||
- 预测市场:流动性与先验脱钩,b = 1.8 × 单盘额度 / ln 2(低先验盘不再更浅:第 38 天在 5% 的盘口押 50,均价从约 +67% 降到约 +10%,50% 的盘口约 +0.5%);份额上限改为 2 × 单盘额度;手续费 2% → 1%。为保持平衡:内幕查处概率 50% → 70%(否则买满上限的期望高于压线),内幕消息价格 1% / 2.5% / 5% → 2% / 5% / 12% 的单盘额度(predsim:高档消息押 1,000 在 50% 盘口平均 +335,原来 +338)。旧存档里的盘口按原来的额度计算。
|
||||
- 收黑币:帮派火并、镇压期间有人上门折价出手 CRT,革命军袭击上层、下层动荡期间是 PSC(每天 35%),Ponero 兑换处开放后偶尔有人出手 Ponero(每天 5%)。只收现金,币进已连接的钱包;市值为房租的 4–15 倍,PSC、CRT 要价是市值的 45–60%,按市值全额带污点;Ponero 要价 70–80%,不带污点。卖家有 5% 是便衣(镇压期间 15%):收下就没收现金并记销赃罪证。开发者模式 F9 有测试入口(Hot coin seller)。
|
||||
- 灰网出售:赃物的货款按“货款 × 赃物热度%”带污点,不再随机。
|
||||
- 人脉升级降价:混币器 700 → 300,Web3 黑市 1,500 → 600。
|
||||
- 手册:交易数量的说明、Poinbase 收的币和交易对、稳定币池、NPC 爆仓与爆仓新闻、保险基金见底的条件、赃物出售的污点、收黑币一节、浏览器显示的范围,8 种语言。
|
||||
- 浏览器:钱包的每一笔进出都记账(统一的记账函数,同时写浏览器和钱包自己的转账记录)。原来只有钱包签名转账、Poinbase 出金和矿机收益,现在还有 DEX 兑换(含黑市自动换币)、质押与解锁、CRA 铸造与销毁、预测盘下注与兑付、情报费、空投领取与钓鱼转走、收益池存取、高息理财、黑市货款放款与退款、混币器提回、Ponero 兑换处换出的币、Tumbler 的谢礼和卖密钥盘的 CRT、用币付款的顾客、收黑币、投毒钱包被转空、地址投毒的 0 币转入。合约和收款方显示名称(DEX、革命军质押池、官方铸造、预测市场、情报贩子、高息理财、Tumbler、空投与收益池的名字)。Ponero 是隐私币,不上浏览器。账本上限 200 → 500 条。
|
||||
- 存档数据版本 3:读旧存档时 Poinbase 主池换成订单簿(按当前价格、新手续费),补上 SPARK/CRC 订单簿,DEX 的 CRT、CRA 池换成稳定币池(保持当前价),其他 DEX 池按新深度重设,保险基金补到新初值。
|
||||
|
||||
## 1.0.0
|
||||
|
||||
正式版:相对 rc11 只有文案审查(见下),功能与 rc11 相同。
|
||||
|
||||
- 8 种语言文案审查:核对上次审校之后新增和改过的 215 条与整段手册,统一术语(储备覆盖率、质押、革命军、状态/成色、确认数等)、去掉残留的旧说法、修正语法和不自然的措辞;入口说明补上挖矿、钱包页;删掉重复键 `black.sell.mult`;中文“显卡鉴定手册”统一为“指南”。
|
||||
|
||||
## 1.0.0-rc11
|
||||
|
||||
- 下单时的预览改成输入时实时更新(不重建页面,输入框不会失焦):Poinbase 现货每个交易对显示买入、卖出的预估得到数量、平均成交价和滑点;永续开仓显示名义价值、预估平均成交价(含滑点)、手续费和强平价;有仓位时显示平仓的预估成交价、手续费、回到账户的 CRC 和盈亏;Web3 互换的预览也改为实时。
|
||||
|
||||
## 1.0.0-rc10
|
||||
|
||||
- 浏览器:转出、转入分成两列,按列宽显示完整地址和名称,放不下时先去名称、再用缩写,鼠标悬停显示完整地址和名称。
|
||||
- RatDigg 矿机的状态面板加了算力(GH/s)、耗电和成色(烧毁显示“已烧毁”),和矿架一致。
|
||||
- 矿机、矿架状态面板里的收款地址在读档、睡觉之后会按标签重新读取,不再显示成“未设置”(地址本来就保存在物品标签里)。
|
||||
- 操纵检出:免查线 2% → 16%,斜率 6 → 3。推价按对数幅度累计,每晚衰减 15%;16% 约对应第 0 天(池深 50,000)一次现货买入 3,900 信用点,随天数池变深免查额度也跟着涨(第 60 天约 8,000);超线后被查概率 = 25% + 3 × (幅度 − 16%)。
|
||||
- 市场深度:永续成交深度倍数 3 → 5,永续单边滑点约为原来的 60%(20,000 名义价值、第 0 天约 8%,原来约 13%);现货池基础深度保持 50,000。
|
||||
|
||||
## 1.0.0-rc9
|
||||
|
||||
- 终端刷新只重建页签栏、滚动内容和消息行,窗口框架和滚动视图保留:滚动位置不再回到顶部(换页或换子页签时才回顶);同一帧里的多次刷新合并成一次。
|
||||
- 货架付平台费页:标题“支付平台费”,去掉“付款币种”字样。
|
||||
- 按住 ✓ 签名的时间随 Gas 档位变化:快档 0.6 秒、普通档 1.2 秒、慢档 1.8 秒(`Tuning.TxHoldSecs` × 档位速度倍数)。
|
||||
|
||||
## 1.0.0-rc8
|
||||
|
||||
- 灰网商店卖货重构:卖货默认是已上架的橱窗(同一商品聚合成一张卡,同一商品倍率相同);“上架更多”进备货页,左边选标价倍率,货架卡片显示聚合库存,用 − / + 调整本次要上架的数量;右下角“货架 N”进付费页,在清单里核对、选币付上架费后才上架。橱窗里每点一次“下架”预备 +1,右下角“确定下架 N”确认,货回储藏区,上架费不退。上架上限改为同时最多 6 种、每种最多 5 件(原来总共 10 件);倍率表不再显示成交天数。
|
||||
- 购物车按钮只在买货页;订单页只显示在途订单(买入未取、卖出待托管放款);取消改价。
|
||||
- 收款币种:橱窗页的“收款币种”选愿意接受的币(PSC、CRT、CRA、Ponero,默认只有 CRT)。每接受一种币,每件在架货每晚多一轮成交判定(轮次概率 = 成交概率 × 该币买家权重,顺序随机),货款以命中那一轮的币到账。
|
||||
- Gas 档位越高,确认越快、进度条走得越快(快档约普通档的一半时间,慢档约一倍半)。
|
||||
- PLEDGER 区块高度每晚随机自然增长 120–170。
|
||||
- 钱包页:选中(连接)的钱包下方列出它持有的币和数量。
|
||||
- 手册出售一节按新流程改写(8 种语言)。
|
||||
|
||||
## 1.0.0-rc7
|
||||
|
||||
- 终端页签重新分组:一级页签为首页、银行、Poinbase、Web3、挖矿、灰网、钱包。挖矿(原 Web3 的挖矿页)提到一级;混币器和商店合成“灰网”(解锁了任一项才出现,两项都解锁时里面再分两页);浏览器挪进钱包页,和钱包列表并成两个子页;Web3 页剩交易、质押、空投、预测、理财。
|
||||
- 首页入口卡片增加挖矿、灰网(解锁后出现)、钱包,各有图标(32×32 像素图 ui_mining、ui_gray、ui_wallets);超过四张分两行,卡片和图标缩小。Web3 卡片的说明改为“去中心化交易与质押”。
|
||||
- “连接钱包”挪到终端顶栏右端,所有页都能连接或断开;没有连接时,Web3、灰网页仍显示提示。
|
||||
- 手册、混币器和商店的解锁说明按新位置改写(8 种语言),术语表加“灰网”。
|
||||
|
||||
## 1.0.0-rc6
|
||||
|
||||
- 钱包和资金页的链上手续费改称 Gas 费(界面和 8 种语言手册);手册里混币器一章挪到出金审查之前;空投范围文案改为“不要代币额度”。
|
||||
|
||||
## 1.0.0-rc5
|
||||
|
||||
### 第十阶段 stage 2:资金页、交易对与部分抵押
|
||||
|
||||
- Poinbase 新增“资金”页(默认页,在现货和永续左边):入金和出金,先选币种(PSC、CRC、CRT、CRA、SPARK)。CRC 可选银行账户或钱包,其他币只能走钱包;入金选钱包时显示 Poinbase 的充值地址(现在五种币都收),出金到钱包要填地址(或选自己的钱包),几秒钟确认进度条走完才到账,手续费固定普通档从转出的币里扣,动画走完前币还在账户里。地址格式或校验位不对拒绝,Poinbase 自己的地址和已知的商家、混币器地址拒绝,格式对但没人用的地址币进黑洞。
|
||||
- 银行页改成只读(现金、房租、CRC 余额);存入和提取挪到资金页的银行账户选项;Poinbase 现货页去掉充值地址和“提到钱包”。
|
||||
- Web3 交易页:交易对改成 X/CRC 池(PSC、CRT、CRA、SPARK 各一个,SPARK 池比较薄),去掉 PSC/CRT、PSC/CRA;支付币和获得币任选,实际经 CRC 中转(CRC 在一端一个池,否则两个池、两次手续费、滑点叠加),预览显示得到数量、池数和损耗;币价表改成“币种 | CRC 价格”。
|
||||
- CRA 改成部分抵押:流通量、CRC 储备、抵押率(铸造要求的 CRC 份额);质押利息以无抵押的新 CRA 付出,稀释储备覆盖率,质押越多越快;革命军挪用储备(先有风声,4~7 天)后覆盖率跌破崩盘线进入三天螺旋,没跌破只是按覆盖率折价;劫掠上层把流通量 9% 的 CRC 并入储备。价格由覆盖率算出,不再按剧本脱锚。
|
||||
- 官方铸造与销毁(质押页):存入 CRC 和 SPARK(比例按抵押率)排 1~2 天铸出 CRA,铸出的直接进质押;销毁换回 CRC 和 SPARK,等待同解锁期,储备不足时 CRC 份额按覆盖率打折;排队单每晚按“系数 × (1 − CRA 价格)”的概率被官方黑掉,整笔丢失(夜间日志提示)。去掉 CRA 与 SPARK 的互换铸销。
|
||||
- 质押可以存 CRA、CRC、CRT、SPARK:后三种先经 DEX 路由换成 CRA 再质押。
|
||||
- Web3 新增“浏览器”页签:按地址查转账记录(自己的钱包、出金、矿机收益等真实发生的转账,全局账本最多 200 条);不需要连接钱包。Web3 页签放不下时折成两行。
|
||||
- 译文校对:铸造 / 销毁沿用术语表(Mint / Burn),页面名与界面一致;空投的“不需要授权”改称“不要代币额度”,避免和钱包授权混淆。
|
||||
- 数值模拟见运维仓库 research/crasim(Python):兑付 CRC 份额取 min(c, R/S) 才不会因抵押率上调被挤兑抽干;挪用比例 40%–80%;游戏内每 200 天崩盘比例约 46%(无质押)到 66%(质押 10 万),预兆到崩盘平均 5.5 天。
|
||||
|
||||
### 第十阶段 stage 1:钱包物品化与小改
|
||||
|
||||
- 解锁 Web3 的物品改放前台(终端、硬件钱包、RTX 60、鉴定指南);离店和睡觉前,前台上属于本 mod 的物品自动收进储藏区,不会被游戏清掉。
|
||||
- 终端首页加第 4 个入口“帮助”,打开 Web3 手册;去掉 Web3 手册这件物品。显卡鉴定手册改用原版鉴定指南的纸张图和“文档”类型。
|
||||
- 涡轮增压器(三种)不能作用于矿架和 ASIC 矿机(原版涡轮会手动触发夜间结算,等于白天多扣一次电);夜间扣电每台机器每晚只算一次。
|
||||
- 永续合约:同一时间只有一个仓位,有仓位后只能追加保证金;保证金和数量合并为一行“保证金金额”;“名义”改为“名义价值”。
|
||||
- 钱包物品化:开局不再自带钱包,解锁送一件硬件钱包,拖到终端上加载(第一个自动连接);钱包页的“销毁”对所有钱包可用,里面的币永久丢失(点两次确认);没有钱包或没有连接时,Web3 页只能看,余额都是 0,用币付款的顾客不再出现。
|
||||
- Web3 页标签栏最右:已连接显示钱包名、地址和“断开连接”,未连接显示“连接钱包”;和钱包页的“已连接”同一份状态。
|
||||
- 空投逐个授权:每个空投先“授权钱包”(在钱包上签授权合约,摘要写明授权范围),再“领取”。
|
||||
- ASIC 矿机去掉修理槽:烧毁后把电子元件(普通、稀有、超科技)直接拖到机器上修,每次收一件,按步骤攒够即修好;不是当前步骤要的元件拖不上去。
|
||||
- 矿机收款地址:矿架和 ASIC 矿机各自在状态面板里设置收款地址(选自己的钱包或手输),挖矿产出每晚按算力占比发到各自的地址;默认不设置,没设置或地址对应的钱包已销毁,这一份产出丢失(夜间日志会提示)。夜间收益不再退回当前钱包,地址对应的钱包没了就是丢了。
|
||||
|
||||
## 1.0.0-rc4
|
||||
|
||||
- 人脉网络里 Web3 的三个升级(入口、混币器、黑市)从单独的 WEB3 标签挪进“基础”页,自成一栏(栏名 Web3),像水商升级那样连成一条。
|
||||
|
||||
## 1.0.0-rc3
|
||||
|
||||
- 去掉反射:游戏的模组扫描把运行时反射算作未声明的权限,rc1 因此被拒绝启用。两处都改掉:电子元件升级矿架时,原版元件工厂改用游戏公开的 `DirectoryMaster.GetFactory` 取得;手册占位符取值(`TuningText`)从反射改成生成的查表(`TuningTable.cs`,单元测试核对它和 `Tuning` 一致)。清单不声明任何能力,扫描结果为无。升级流程重新走通:普通 ×4 解锁第 3 槽,稀有 ×1 第 4 槽,稀有 ×2 第 5 槽。
|
||||
|
||||
## 1.0.0-rc1
|
||||
|
||||
### 第九阶段:剧情与收尾
|
||||
|
||||
- 多语言第二轮审校(逐语言通读 UI 与 16 章手册并交叉复审):采用 de 39、fr 56、es 34、pl 37、ru 45、ja 142 条(ja 里约一半是全角标点、×、〜 等机械统一)。要点:天数不再缩写、Tumbler 称谓与 Key-Drive 统一、手册页签名对齐界面、ASIC 时代统一、修正数处误译(俄语手册首章“卖出”写成用交易币付款、永续/挖矿章、日语质押章“向池子付款”等)。
|
||||
- 真伪依据改版:检视面板最前面四行是风扇数、供电口、背面丝印、序列号,四项全部符合标称型号才是正品,任何一项不符即为假冒;其后是型号和四项成色。风扇数、供电口各自独立(假卡不再固定两项都对不上),假卡四项各自露出破绽,至少一项,平均约 1.5 项(`Tuning.FakeSignChance`)。去掉检视面板和指南里的“卖家的说法”,该机制只在后台生效。指南里不再用“档次”,改称型号;背面图上画出序列号。
|
||||
- 矿架改版:图 4×4 格(原 3×3;5×4 放不进任何容器,改回 4×4);去掉升级槽位,改成把电子元件拖到矿架上就投入升级(每次一件,和游戏里别的机器一致);原升级槽位那一栏换成只读的状态面板(显卡数、耗电、算力);不显示显卡磨损外观。
|
||||
- 修正:电子元件拖到矿架上原来会被元件自己的判断否决(游戏取三方判断的与),改为在原版电子元件(普通、稀有)上追加“作用于矿架”的判断,升级才真正可触发。升级流程用探查命令和真实鼠标拖拽都走通(4 次拖拽解锁第 3 槽):普通 ×4 解锁第 3 槽,稀有 ×1 第 4 槽,稀有 ×2 第 5 槽,满级后不再收;5 张卡放满窗口显示 5/5。
|
||||
- 解锁“Web3 治理社区”时,矿架优先放进机器区(没有位置才退回原来的送货位置)。在干净存档里走通:人脉网络 Web3 页买下 400 / 700 / 1500 三项,扣 2600,终端、显卡、鉴定指南、Web3 手册到手,矿架在机器区,终端里混币器和商店页签出现。
|
||||
- 重译:矿架升级提示(拖到矿架上)、鉴定指南“指出”一页(改后的按钮规则);矿架状态面板标签校对(俄语“状态”避开与成色同词,德语、俄语、日语“显卡数”改用各语言已有的显卡词,法语、波兰语算力标签缩短)。删除不再使用的旧键 18 个(档次、依据、旧升级槽位等)。
|
||||
- 各语言下核对鉴定指南与检视面板的排版:示例页的“最终价值”改为各项折价相加(原来用带种子的卡现算,被健康度重算覆盖,数字对不上);长语言下第 1、3、4、5、6 页的插图按剩余空间自动缩小(原来德语、俄语等超出纸面);小节标题折行时下推;检视面板名称列加宽(德语“Rückseiten-Aufdruck”不再被截),去掉成色行末尾的“(卖家说:…)”;波兰语挡板译成“Zaślepka”(原来误译成“鲱鱼”)。
|
||||
- 旧存档兼容:外观只有 5、6 位的旧版假卡读取时按旧规则补上风扇数、供电口破绽(档次相同的不补),单元测试覆盖。
|
||||
- 长局与存档往返验证(探查命令推进,不含顾客流程):在干净存档里真实买下三项升级后推进到第 20 天,夜间结算、挖矿、黑市出售与蜜罐、矿机时代、停电、预测与骗局事件都按日运行,没有异常;存档并重新读档后,钱包价值、污点、币价、报告页、矿架升级进度(3/4)、假卡的 8 位外观都一致。
|
||||
- 检视面板的型号鉴定只留一个“指出型号”按钮(第一行,型号);风扇数、供电口、背面丝印、序列号四行只读,四项全部符合才是正品。
|
||||
- 检视面板的型号行右侧显示“标签价”(当前报价,随指出和改标签实时变化),鉴定客户的估价框同步。
|
||||
- 显卡鉴定指南的鉴定示例由 1 个增至 5 个(成色很差、假冒、轻微使用、全新),共 13 页。
|
||||
- 二手贩子的卡按卖家调整健康度:老实人 72–97、中间商 55–85、骗子 42–72,平均每张卡成色有问题的项(叶片、金手指、挡板、封条,共 4 项)约 0.5 / 1.5 / 2.5(原来三者都是 25–85,约 2.4)。范围进 `Tuning.UsedHealthMin/Max`。
|
||||
- 显卡鉴定指南改为游戏原版的纸质指南样式(笔记本背景、委员会页眉、居中标题、插图加图注、“价格不变 / -n%”标注、末页鉴定示例,共 9 页,插图用检视台的大图),文案改成名词标题加陈述句,用词与原版鉴定指南一致(假冒、品相、价格不变)。
|
||||
- (已被上一条取代)显卡鉴定手册曾做成阅读窗口(和 Web3 手册同一个窗口,共 8 页,8 种语言);外观折价六个数字进 `Tuning`(`CardFanDust` 等),手册用占位符取值。物品提示缩短为一句。
|
||||
- 鉴定样例测试按钮(`Showcase: next dealer / appraisal case`),展示页的显卡鉴定专页用它截图。
|
||||
- 鉴定显卡的检视弹窗:第一行标签“型号真伪”改为“型号”(各语言同改),指出之前不再写“检查:供电口与风扇数、序列号、背面丝印”这行依据;指出之后仍在下方列出查到的问题。
|
||||
- 带首尾空格的拼接文字(“ (seller said: {0})”等 10 条):英文原先有的没加引号,被游戏读表时吃掉;其余语言翻译时也丢了。已补引号、按英文补回空格,并加测试。
|
||||
- GPU 检视的行名放不下时自动缩字,“型号真伪”各语言改短。
|
||||
- 多语言审校:对 de fr es pl ru ja 各审一轮,共提出 125 条修改,人工核对后采用 116 条(拒绝:俄语一条漏译成英文、日语把按钮缩得丢了 CRC、两处手册章节被整段改写、少数理由不成立的)。主要是矿工译法(Miner / майнеры)、天数缩写、术语不一致(Compliance-Prüfung 等)、稳定币 Pegged 的译法、语法错误。
|
||||
- 交易终端窗口加大:默认 1200×900,mod 设置里可选 828×680(旧大小)、1200×900、1400×1000。窗口大时左右栏、表格列、货架列数、K 线图(3 倍像素)、首页卡片、订单两栏、钱包表按多出的宽度放宽,文字放大到约 1.24 倍(上限 1.3,行高和商品卡同步)。
|
||||
- mod 设置(分类:界面、剧情、难度):终端窗口大小;Tumbler 剧情开关;风险倍率(骗局、跑路、钱包投毒、地址劫持、钓鱼概率)和挖矿产出倍率,档位 ×0.5 / ×1 / ×1.5 / ×2,领域层 `Scales` 读取。分类名要等本地化表可用后再登记。
|
||||
- 多语言:新增 de fr es pl ru ja 六种语言表(连同 zh en 共 8 种,对应游戏主菜单的语言)。英文表是源文,其他语言由 AI 分块译出(术语表 `docs/i18n-glossary.md` 在运营仓库,游戏已有的词用官方译名),未经人工校对,文件头有说明。键集合、占位符、`§ ¶ \\n` 标记由单元测试逐语言核对,非中日语言里不得出现汉字或假名。
|
||||
- 多语言布局:表格单元、按钮文字放不下时自动缩小字号(最小 68%)再省略,商品名限定两行内缩放;de fr es pl ru 的钱包表、手册章节列表、硬件钱包粘贴键按语言放宽;ru de 等少数过长标签改短(永续“加保证金”键、收益池列头)。
|
||||
- 中文“匿名币”改称“隐私币”(英文 privacy coin),手册、黑市标签同步。
|
||||
- 英文手册里写死的“六天”“7 天”改为占位符 `{BmBulkDays}`、`{AmlWindowDays}`,和中文一致。
|
||||
- 手册里剩下的写死数字也进了 `Tuning`:出金审查污点系数 `AmlTaintMult` 与超额权重 `AmlExcessWeight`、出售速度界线 `BmSellFastMult` / `BmSellDay1Mult`;剧情联动的期限和涨幅改用已有的 `Story*` / `Tumbler*` 常量占位。占位符新增 `{Name:+%}`(倍数显示成涨幅)。
|
||||
- 文案审查(逐行审查后人工核对):中文界面约 70 行改为中立陈述(去掉括号说明、祈使句、口语;夜间日志里的“黑市:”改“商店:”;“安保部”统一为“治安部”),手册里的口语和劝说句改写。保留“跑路”(题材用语)、“健康”(游戏用语)。
|
||||
- 商店卖货页改为左右分栏(和买货页一致):左栏标价倍率表(含预计成交天数)、好评、上架数、全部上架,右栏货架;订单页改为买入、卖出两栏。倍率档位 `BmSellMults` 进 `Tuning`。永续持仓表列宽调整,表头不再重叠。手册合并为 16 章(混币器与匿名币、订单与出售),章节列表一屏放得下。
|
||||
- 手册“银行与交易”章加 PSC 全称(Probably Stolen Coin)说明,只在此处解释一次。
|
||||
- Web3 手册改为阅读窗口:使用手册物品打开 PLEDGER 风格窗口,左边 18 个章节,右边章节全文;章节在 `guide.web3.text` 里用 `§` 分隔(`¶` 为段落)。手册里的"黑市"(指商店处)改称"商店"。修复手册文本里未转义的双引号(英文手册在游戏里只读到 1,610 字符)。新增调试按钮"Give handbooks (test)"。
|
||||
- 商店补验证(游戏内):逐家自动换币(购物车里一家商家用 CRA 换 PSC 付清,160.92 CRA → 1.493 PSC,那一家从购物车里消失,另一家保留);账单页(平台);英文界面(Shop 页签、卖家列表、商家信息头、购物车、付款面板都正常)。卖家列表的缩写地址改成类型加后四位(如"Used GPUs ·2077"),英文长名不再折行重叠。
|
||||
- Web3 商店改版(`ui-trial` 分支):
|
||||
- "Web3 黑市"改名"Web3 商店"(页签、升级项、提示;黑市声望是游戏派系,名字不变)。
|
||||
- 点左栏卖家后,右栏最前面是商家信息:名称与地址、成交数、好评、到货天数、收的币、是否接受提前放款;平台是"立即到货"和收的币。
|
||||
- 购物车:货架上的"购买"改成加入购物车(同一件再点数量 +1,封顶库存);商店页右下角悬浮购物车按钮("购物车 N",点开进结算页,结算后清零;读档清空)。
|
||||
- 结算页两栏:左边购物车详情(按商家分组,每行 -、数量、+、删除,接受提前放款的商家可选托管 / 提前放款,合计);右边付款:每家商家的收款地址不同,所以只做逐家付款——每家选它收的币、生成账单、在钱包里转账;钱包里别的币够付时,每家还有自动换币(多付 8% 滑点、签名一次付清这一家)。统一结算已去掉。
|
||||
- 游戏内验证:平台加两件、再加一家商家的货,购物车 3 件;结算页两栏显示正常,每家商家各一块付款选项(收的币、需付金额、钱包余额、生成账单、够付时的自动换币),点平台的"生成账单"得到平台收款地址和金额。自动换币在改成逐家之前验证过(66.96 CRA → 0.6212 PSC 后成交);改后的逐家自动换币和账单付清没有再走一遍,也没验证英文界面。
|
||||
- 黑市买货页重排(`ui-trial` 分支):左栏是卖家列表(平台和各商家,选中行反色,商家写类型和缩写地址),右栏是 3 列货架;币种和数量不再摆在货架上方。点"购买"后右栏换成付款面板:数量(库存内 ×1 / ×5 / ×10)、付款方式(商家接受提前放款时才有)、合计、付款币种(该商家收的币)和"生成账单";下面是自动换币——钱包里别的币(够付)按 8% 滑点换成商家收的币,一次合约签名完成(`BmAutoSwapSlip`);没有够用的币时写明。上架费、改价费、一键上架同样在付款面板里选币(平台收 PSC、CRT、CRA)。各类商家收的币:硬件技术类 PSC / CRT,违禁和个人卖家 CRT / 匿名币,农业养殖水务酿酒 PSC / CRA(`Merchants.Accepts`,界面里限制,域层下单不限)。游戏内验证:平台买一件商品,CRC 自动换币 224.64 CRC → 2.0842 PSC(208 信用点等值)后成交,货进储藏区;直接生成账单显示收款地址和金额;商家货架切换和付款面板正常。没有验证:卖货页改价、一键上架的付款面板、英文界面、数量选择(库存只有 1 件)。
|
||||
- 钱包页按钮:操作键放到数据格右边的纸面上(和顶栏页签同样的黑色触控键,不再压在污点字段上);选中行只反色数据格;状态"已连接"靠右。
|
||||
- 新手期调整:低端显卡算力提高——RTX 60 1.0 → 1.8 H、RX 70 0.8 → 1.4 H(价格、耗电不变)。开局送的一矿架一卡,第 1–7 天日均净收入 14 → 33(电网电价),第 15–30 天 6 → 18;再买满 4 张同款卡的矿架 33 → 82/天,每加一张约 10 天回本(原来 24 天)。每张卡每千瓦时的产出仍低于中高端,一个矿架只有 4 个槽位,满槽 4×RTX60 约 7 H,4×RTX70 是 20 H,中后期自然要换更高档次。ops `research/starter` 有各档位的逐段结果。
|
||||
- 手册补写出金审查的全部规则(界面不显示额度和命中概率:单笔 5 倍房租、7 天累计 15 倍房租、污点 10% 起、混币和被标记地址 +30%、上限 90%、轻度 / 重度的后果、手续费和税)和"销毁钱包前自己转出持仓与存款"。
|
||||
- 金融审查(独立的数值审查,核实后采纳一部分):
|
||||
- 采纳:`CrcHaircut` 0.95 → 0.85(减记后的持有量比例高于脱锚买入价 0.905,抄底即使遇到减记也不亏,减记形同虚设;现在遇到减记亏约 6%,没遇到仍赚约 10%);`SideArbRate` 0.5 → 0.75(CRA 螺旋时 PSC/CRA 池滞后公允价 43–80%,持 CRA 的人能榨池子);gas 盘公开价"不知道相位"的权重 0.5 → 0.15(`PredictGasBlind`,原来数清周期的玩家胜率 96%、每周净赚约 1,400)。
|
||||
- 没有采纳:`PerpOpenBuffer` 0.02 → 0.01(只让名义 1.5 万以上的 5 倍大单能开,而且贴着强平线开,收益小风险大);派系盘"队列为空必为否"——这个结论的前提是玩家看得到排期,而排期对没有特权的玩家是隐藏的,对有传闻纸条、特权或买了情报的人本来就是内幕单,会被查处;先验每天 6% 是估计值,要用真实的游戏观察校准;NPC 开局算力偏低(回本约 10 天)和前期节奏偏快——设计时的取舍,保持。
|
||||
- 综合模拟(portfoliosim,120 天):纯挖矿第 30 天 22%(符合目标);全做合规约 34%;"粗心出金"(脏币直接出金 + 理财卷走)罪证峰值 750 以上,第 35–45 天逮捕率 100%。
|
||||
- 外部评审(整体评审报告,逐条核实后)修复的真实问题:
|
||||
- 销毁钱包留在里面的持仓和存款会随钱包没有:评审建议拦截或回退,用户决定保持现状(和真实钱包一样,要自己先转出),所以撤回了我加的拦截和回退,只在手册里写明。
|
||||
- Tumbler 剧情进度在生成顾客时就推进:当天没聊完、被清场或读档重来,进度已经走了,最糟的是第 3 次(三选一)没选就跳到第 4 次的"没做选择"分支,剧情报废。改成对话真正走完才推进;第 3 次在做出选择时推进;没聊完明天照样来。游戏内验证:第 1 次聊完日志"进度 1",没聊完的第 2 次不推进。
|
||||
- 夜间结算加幂等保护:同一天已经结算过就跳过,防止其他 mod 或调试让钩子触发两次造成双重扣费。
|
||||
- 预测盘口读游戏的 `futurEvents` / `futurEventsDay` 两个并行列表时加了下标保护。
|
||||
- 核实后没有采纳:静态变量串档(`ClosePrice` 等每晚结算前先赋值再用,`Pending` 读档时已清;实际无串档)、除零(SPARK 螺旋也只到约 0.5、CRA 最低 0.02、全网算力有 0.8 的可用性下限,不会为零)、全局随机数流拆分(设计取舍)、`Charged` 字典增长(体积极小)。报告里还有几处引用错误(页签数量、不存在的 `out_fullsim.md`)。
|
||||
- 收尾补验证(游戏内,用游戏自己的开日流程:调试"Run night"和 `day 1` 过夜,墙上的卷帘门按钮开门):
|
||||
- 伪造转账顾客:新增调试入口"Coin buyer forged"。开口"CRT 我已经转过去了,截图给你看……"(正常顾客说"我用 CRT 付,链上确认要一会儿");成交 4 件共 118 信用点后现金没变(信用点被扣回),日志逐件记"伪造转账",晨间日志列出四条"拿走了……说付了……链上没有这笔"。
|
||||
- 内幕被查:线人排期的停电盘口押「是」花 600(2,046 份,超过上限的 40%,标内幕),结算夜"内幕下注被查:本金和收益 2,046 全部没收,记诈骗罪证",罪证账本 FRAUD 380。
|
||||
- 骗局池跑路:第一晚"收益池「Test Scam」跑路,主钱包 存的 563 CRC 没了"。钓鱼授权不撤销时"主钱包 的 9,000 CRT 被「P0inbase」用授权转走了"。
|
||||
- 永续资金费:多头 2 倍、资金费率 0.3%:保证金 1000 → 994.06 → 987.97 → 981.73(每晚约扣名义价值的 0.3%)。夜里在日志里记各仓位的保证金、资金费率和标记价。
|
||||
- 报纸:调试"Chain drama"后报纸上出现"链上拥堵"和"POINBASE 公告:充值地址迁移"(钓鱼公告)。
|
||||
- Tumbler 自然开始:解锁混币器、第 35 天开门,日志"Tumbler 剧情开始:第 36 天第一次上门",同时当天的预测盘口补盘和开盘钩子正常。
|
||||
- 密钥盘:`inspect` 看到 CONTRABAND_ITEM_TAG、等级 CONTRABAND_LEVEL_HIGH、类型 CONTRABAND(游戏自己的搜查查的就是这几个标签);真实被搜出来的路径没有触发。新增调试入口"Give key drive""Perp: PSC long 1000 x2"。
|
||||
- 发现:`Run night`、`day N` 都不走开门(OnShutterOpened),所以以前只靠它们的测试没有跑过每天开门的逻辑(市场开盘波动、K 线开盘、预测补盘、Tumbler 开始、顾客相关钩子);这些要点墙上的卷帘门按钮开门才会触发。
|
||||
- 仍没有在游戏里验证:ASIC 自然暴毙和黑市收货、永续穿仓后 30 天拉黑和没收单、杰克逊柜台上钱包的标价、游戏输入框里 Ctrl+V、密钥盘被真实搜查翻出、Serpico / Eleanor 剧情在游戏自己的对话里选择后的联动(只用调试设置过选择)。
|
||||
- 界面文案去口语化:理财子页改为"收益池""发行理财";高息理财页的"风声:有人在议论"改为"举报风险:低 / 中 / 高","开张"改为"发行","昨晚新存入""今晚要付利息""自己垫付的利息"改为"昨日存入""今晚应付利息""自付利息合计";预测、情报、空投、收益池、K 线图、混币器的提示句一并改成陈述句(如"今日无开放盘口""需用授权钱包签名")。对话(Tumbler、假客服、顾客)不改。
|
||||
- 理财页合并:Web3"理财"页签分两个子页——"存钱(别人的池子)"是 NPC 开的第三方收益池(原来在质押页下面,挪过来了),"发行(自己当庄)"是自己开的高息理财。页签一直显示,第 15 天前"发行"子页只写哪天起能开。手册里两处位置说明一并改了。游戏内验证:两个子页切换、收益池表格和存入金额、发行页开张选项都正常。
|
||||
- 补验证(游戏内,阶段 5–9 只有单元测试的路径):
|
||||
- 罪证与声望:高息理财被举报崩盘后罪证账本 FRAUD 400;手动卷走后下层声望 45 → 0、FRAUD 400;Tumbler 举报结局现金 +1,200、治安部声望 0 → 12;卖给黑市结局黑市声望 75 → 82(游戏的声望计算有自己的加成,比设定的 +5 多)。新增调试入口"Dump crimes and reputation"(罪证账本、证据、三派声望、现金写进日志)。
|
||||
- 骗局:签名撤销钓鱼授权后(PLEDGER"授权已撤销"),三晚 CRT 没被转走(2,998.5,只扣了 1.5 手续费);时间锁池子取款两晚后到账("收益池「Test Lock」取款到账:主钱包 收到 500 CRC")。骗局池三晚没跑路(每晚 18%,三晚都没跑的概率约 55%),跑路仍只有单元测试。新增调试入口"Scams: phishing approval + scam pool"。
|
||||
- 英文界面:终端、空投、预测(含 K 线图和阈值线)、Poinbase 现货与 K 线图都正常;"On-chain wallet Main wallet: CRC"改成"Main wallet: CRC"。测完已把游戏语言切回中文。
|
||||
- 仍没有在游戏里验证:伪造转账顾客(要自然出现的用币顾客)、内幕被查、骗局池跑路、密钥盘被搜查翻出、剧情的自然触发(第 30 / 40 天以后)。
|
||||
- 9.1 剧情联动:每晚读游戏剧情线的选择,每个只生效一次,改动本 mod 世界的倍率(存档里的 `StoryMods`),第二天报纸头版登一条新闻。选择是玩家自己做的,市场要过几天才反应完(SPARK 分 5 晚走完),可以抢在前面用永续和预测盘下注。
|
||||
- 塞尔皮科的证据交给革命军:CRA 补贴池 +10,000,30 天内螺旋概率减半,SPARK 五晚内涨 20%;交给黑市:CRT 脱锚、镇压时被黑市出卖的概率永久减半;交给治安部:30 天内出金审查命中率 ×1.5、混币器制裁概率 ×1.5、操纵检出和内幕查处 ×1.3;举报他或他死了:没有影响。
|
||||
- 埃莉诺泄露数据盘:CRC 托管银行减记的概率翻倍,SPARK 五晚内涨 15%;交回数据盘:CRC 脱锚概率减半。
|
||||
- 伦警官被捕:14 天内出金审查、操纵检出、内幕查处 ×1.3(和治安部整顿叠加)。
|
||||
- 无尽模式关闭角色剧情线,这些选择不会出现。放贷人 Lou 被捕没有接(借贷暂缓)。
|
||||
- 游戏内验证:调试入口设置"证据给革命军、泄露数据盘、伦警官被捕"后过一夜("Run night (test)"),日志三条"剧情联动生效",第二天报纸头版登出三条新闻。没有在游戏里验证:真实剧情对话里做出选择后的联动、各倍率在游戏里的实际效果(单元测试覆盖:出金命中率上升、CRT 脱锚减半、SPARK 推涨合计 ×1.2、叠加)。
|
||||
- 9.2 本 mod 自己的剧情线:混币器运营者 Tumbler。解锁混币器、第 30 天起,四次上门(游戏的对话顾客,开始日、+3、+5、+9 天,错过的往后补):
|
||||
1. 自我介绍:混币器是他写的。
|
||||
2. 治安部在查链上混币服务。当晚混币器节点被查封 4 天,报纸登"治安部查封混币节点"。
|
||||
3. 求你藏密钥盘,三选一(游戏自己的选项界面):
|
||||
- 藏好:给你一件"密钥盘"(违禁品,高级,价值 600,游戏自己的搜查会翻出来记罪证)。第 4 次他来取:密钥盘还在就收走,留 1,000 CRT 谢礼进当前钱包,混币器手续费永久减半、匿名集 ×1.5;弄丢了(被搜走、卖掉)他只说"算了"。
|
||||
- 举报:马上拿 1,200 信用点赏金、治安部声望 +8,混币器永久关停(在途的照常提回,不能再存),报纸"混币器运营者落网",第 4 次不再上门。
|
||||
- 卖给黑市:3,000 CRT 进当前钱包(一半带污点)、黑市声望 +5,之后混币器手续费 ×1.5、跑路概率 ×4,报纸"混币服务易主";第 4 次他上门质问。
|
||||
- 新画了密钥盘的像素图(深紫数据棒、金属接口、红色指示灯)。
|
||||
- 补测(游戏内):举报结局现金 +1,200(1,000,080 → 1,001,280)、治安部声望 0 → 12(加 8,游戏声望计算自带调整)、没有第 4 次上门、混币器页"状态:已关停"并拒收新存入;卖给黑市结局黑市声望 75 → 82(加 5,同样有调整),第 4 次上门质问。高息理财:被举报崩盘后罪证账本出现 FRAUD 400;手动卷走后下层声望 45 → 0、FRAUD 400。
|
||||
- 游戏内验证:调试入口"Tumbler: next visit now"依次叫进四次,第 1、2、3 次对话正常,第 3 次出现三个选项;选"藏好"后日志"选择 1";第 4 次取回密钥盘,晨间日志"Tumbler 取回了密钥盘,留下 1,000 CRT 谢礼(已转入 主钱包),混币器手续费减半"。没有在游戏里验证:举报和卖给黑市两条结局(单元测试只覆盖倍率)、第 2 次之后的查封和新闻、搜查翻出密钥盘、自然触发(第 30 天、已解锁混币器)。
|
||||
- 9.3 收尾经济复核(ops `research/fullsim`):挖矿收入全部再投资、钱够就买矿机,120 天平均只买到 3.4–3.9 台(矿机商每周 25%、一次一台),没有滚雪球;第 30 天金融线占总收入 19–22%(目标 20–30%),专心买矿机的玩家第 80–90 天峰值 37–44%,第 90 天减半和矿机时代后回落。没有改数值。
|
||||
- 报纸修复:报纸按重要度排序、最多登 4 条;mod 新闻原来的重要度是 2,游戏事件一多就被挤掉(此前各阶段"报纸新闻没有验证"的原因)。改为默认 5(游戏事件多在 4–7),剧情联动 9。
|
||||
|
||||
### 行情图
|
||||
|
||||
- K 线图标数字:图里用一套 3×5 像素数字字体(放大 2 倍后约 6×10),和像素风格一致。右侧刻度栏(宽 22 像素)标三条网格线的价格;最新收盘价是黄底价签,网格刻度离它太近时让开;预测阈值线的价格用蓝色标在刻度栏;成交量区右上标这一屏最大的成交额(≥ 1 万写成 "36k");底部每逢天数是 5 的倍数的蜡烛下面标天数并画一个刻度点。价格位数随大小变:≥ 100 不带小数,≥ 10 一位,≥ 1 两位,小于 1 三位(".995")。图宽 206 像素(显示 412)。游戏内验证:PSC 刻度 113 / 81.3、价签 91.8、量柱 36k、日期 −10 … 15(测试存档在第 16 天,调试入口往前补了 30 天,所以出现负数;真实历史从第 1 天开始)。
|
||||
- 所有可交易资产都有日 K 和成交量:PSC、SPARK、CRT、CRA、CRC、Ponero。开门时每个币开一根(开盘接昨天收盘),夜间结算在价格更新前收盘;稳定币和 SPARK 的价格在夜里变,变动算进第二天那根。成交量:市场的量 = 主池深度 × 各币比例(PSC 12%、CRC 10%、CRT 6%、CRA 4%、SPARK 3%、Ponero 1%)×(1 + 8 × 当天的涨跌与振幅)× 0.6–1.4 的随机,波动越大成交越多;你的量包括 Poinbase / DEX 兑换(两边的币都算)、SPARK 铸销(SPARK 和 CRA)、Ponero 兑换、永续开平仓(按名义价值,计入 PSC 或 SPARK)。
|
||||
- 图上方加一排币种按钮(Poinbase 现货页、Web3 交易页各自记住选的币,Ponero 要黑市解锁后才出现);永续页显示当前选中的品种;预测页仍是 PSC。均线改为先画,蜡烛盖在上面,贴着锚的稳定币不会被均线遮住。
|
||||
- 游戏内验证:Web3 交易页切换 PSC / SPARK / CRT 都正常,SPARK 有完整的蜡烛和放量,CRT 在锚上是一条线(30 天里没脱锚)。没有在游戏里验证:脱锚时稳定币的图、Ponero、玩家各类成交计入量柱(只看过 PSC 现货的青色柱)。
|
||||
- PSC 日 K:存档里新增逐日 K 线历史(`CandleBook`,保留 60 天)。开盘接前一天的收盘价(币是全天候交易的,夜里的回归和开门波动算进当天这根,没有跳空);最高 / 最低只取白天真实发生过的价格(开门波动、NPC 大户、插针、玩家在 Poinbase 的大单),不编造日内走势;收盘是夜间结算前、插针回去之后的价格。成交量分大户和玩家两份。旧存档没有历史,从接入当天开始记录。
|
||||
- K 线图:运行时画在一张 188×97 的纹理上,点采样放大 2 倍显示,和游戏的像素风格一致。最近 30 根,涨绿跌红、影线、黄色 7 日均线(永续资金费按它算),下方成交量柱(灰 大户 / 青 你的成交),当天还没收盘的蜡烛画成空心;上方一行写最高、最低、收盘和涨跌幅。出现在 Poinbase 现货页、永续页,以及预测页选中 PSC 价格盘时(加一条蓝色阈值虚线)。
|
||||
- 调试入口"Chart: run market 30 days":用真实的行情过程往前跑 30 天并记录蜡烛(会改动这一局的 PSC 价格,只在测试存档用)。
|
||||
- 游戏内验证:三处都显示正常,30 根蜡烛、均线、成交量柱、阈值虚线(PSC 价格 ≥ 104)。没有在游戏里验证:按真实日程一天天积累(只用调试入口跑过)、英文界面。
|
||||
|
||||
### 第七阶段:预测市场、操纵与骗局(7.1、7.2、7.3)
|
||||
|
||||
- 阶段 7 数值总复核(ops `research/stage7sim`,用真实的域层,30 天平均每天净收益,对照原版第 30 天约 1,990 / 天的毛收入)。改动:
|
||||
- 预测内幕被查改为本金和收益全部没收(原来只退本金,等于没有风险);先买后卖、赶在结算前离场,卖出有赚时同样按内幕查处(原来卖出不查,"开盘买、隔夜涨价卖"是零风险的 +47~+70 / 天)。复核后:每 5 天一条消息、5% 盘口下 300 持有到结算约 +230 / 天、亏钱概率约 0;下 1500 持有到结算平均 +3(第 30 天)、亏钱概率 64%——小单安全,大单被查。
|
||||
- 高息理财的罪证 1200 → 400:单次记 1200 会直接越过 300 的逮捕线(calibration §1.4),卷走一次等于游戏结束;400 和预测、操纵的罪证上限一致,需要叠加其他罪证才危险。
|
||||
- 第三方收益池单池上限 2000 + 60 × 天数 → 4000 + 120 × 天数:原来最好的策略每天只赚 40,没人会去碰;现在"只存骗局概率低的"约 +80~+114 / 天、30 天亏钱概率约 9%,全存约 −25~−34 / 天、亏钱概率约一半。
|
||||
- 水纯度盘的阈值从各 4 档减到 2 档(下层 8300 / 8700,上层 9050 / 9100):纯度先验精确、没有信息可挖,原来占了候选盘口的大头。
|
||||
- gas 盘的公开价改为一半按真实相位、一半按不知道相位:七天周期是链上公开的,原来盘口完全不看相位,数清周期的人每盘都能稳赚。
|
||||
- 空投:钓鱼空投改为七成要无上限授权、三成要奖励 20–100 倍的大额授权(看着像"有限授权"),转走时不超过授权额度。全领 30 天约 −94 / 天、几乎必亏;只领没问题的约 +14 / 天。
|
||||
- 插针抄底:向下插针买 3000 / 10000、第二天卖回,约 +13 / +29 每天,亏钱概率约一成;保持小额,不改。
|
||||
- 交互:让玩家看得懂市场怎么动:
|
||||
- 盘口列表上,夜里价格变化超过 0.02 的写"(昨晚 0.03 ↑)";变化超过 0.15 的进晨间日志,附上第一条线索作为原因,例如"预测盘「第 19 天:出现「停电」」价格 0.03 → 0.59(排期:第 19 天开始)"。
|
||||
- 预测页左栏底部"历史(开盘均价 / 实际发生)":按盘口类型统计开过几个、开盘均价、实际发生的比例,玩家能看出哪类盘口系统性地定价偏高或偏低(例如新闻事件开盘均价 0.03、实际 33%)。
|
||||
- 可交易的盘口排在列表前面,已封盘的排后面。
|
||||
- 游戏内验证(用"Run night (test)"走游戏自己的开日流程):调试排一个第 19 天的已知停电 → 第 16 天开盘 0.03 → 第 17 天晨间日志"0.03 → 0.59(排期:第 19 天开始)"→ 第 18 天"0.59 → 0.82"→ 第 19 天夜里结算"是",历史面板"新闻事件:3 个,开盘均价 0.03,发生 33%"。注意:AutoMod 探查的 `day N` 不走游戏的开日流程,排期事件不会触发,测这类盘口要用"Run night (test)"。
|
||||
- 7.3 NPC 骗局:
|
||||
- 插针:第 10 天起,每天开门 7% 概率价格被瞬间打上或砸下 15–30%(PSC 主池);七成当晚回去 60–100%,三成是真的(不回去)。永续当晚的标记价仍用"开门价与收盘价的平均",开门价取插针前的价格,所以强平只吃一半;预测盘和夜间结算读回去之后的价格。
|
||||
- 空投与钓鱼授权(Web3 新增"空投"页签):每晚 35% 概率出一个空投,2 天内可领;四成是钓鱼。正规空投不要授权或只要 10–60 的小额授权,奖励 20–120 CRC;钓鱼空投七成要"无上限授权"、三成要奖励 20–100 倍的大额授权,名字六成是仿冒(0/o、1/l、m/n 之类),领到的只有标称奖励的 5%,1–2 晚后在授权额度内把那个钱包里的这种币转走(污点按比例一起走)。领取是合约调用,PLEDGER 核对页写明授权范围;右栏列出当前钱包的授权,可以签名撤销,撤销后就转不走。
|
||||
- 第三方收益池(质押页下面):同时最多 3 个,每晚 25% 概率新开;日息 1 / 2 / 3%,储备、时间锁、审计看得见,是否骗局看不见:骗局概率按日息 15 / 40 / 75%,有时间锁 −25%,有审计 −20%。正规池从储备付利息,储备付不起时退本金关闭;骗局池照常显示利息,每晚 18% 概率跑路,存款和在途取款全没。有时间锁的池子取款要等 2 天(等的时候跑路也没了)。单池上限 2000 + 60 × 天数。存入、取出都是合约调用,污点与成本随存款进出。
|
||||
- 假客服:第 10 天起每天 4% 概率,一位"Poinbase 客服"上门说账户被风控,要把 300–1500 CRC 转到"安全地址"。地址记为骗子地址,转过去的币就没了,晨间日志点明。
|
||||
- 伪造转账:第 10 天起用币付款的顾客里 8% 是骗子,开口说"已经转过去了,截图给你看,赶紧给货"(正常顾客说"链上确认要一会儿");成交后信用点被扣回、币不到账,晨间日志列出谁拿走了什么。
|
||||
- 假买墙、貔貅币依赖 NPC 项目币,挪到阶段 8 和发币一起做。
|
||||
- 游戏内验证:空投页列出 4 个空投(含"Revo1ution DAO 授权 PSC 9,120""PSC Foundation 授权 CRT 无上限");签名领取钓鱼空投只得 4 CRC,授权出现在右栏;领"Revo1ution DAO"后过夜,晨间日志"主钱包 的 20 PSC 被「Revo1ution DAO」用授权转走了",钱包 PSC 归零;收益池表格(日息 / 储备 / 时间锁 / 审计 / 存款)显示正常,签名存入 500 到 3% 的池子,三晚后 546;插针让 PSC 估值 2000 → 2445;假客服上门对话。没有在游戏里验证:撤销授权、骗局池跑路和正规池退本金(单元测试覆盖)、时间锁取款到账、伪造转账顾客(要自然出现的用币顾客)、转给假客服地址后的日志、英文界面。
|
||||
|
||||
#### 7.1、7.2
|
||||
|
||||
- 高息理财改用链上钱包:开张(宣传费 800 CRC)和卷走都是合约调用,用当前钱包签名;产品记下发行钱包,每晚垫付的利息从它出,卷走的池子进它(污点全额),卷走要用发行钱包签名。游戏内验证:主钱包签名开张 6%,三夜后签名卷走 1634,钱包 CRC 1000 → 200 → 1833,污点 1634,卷走手续费 1.13 CRT。
|
||||
- 柜台线人接进预测市场:游戏里卖消息的顾客(乞丐、线人,提前 1–4 天说出新闻事件)、传闻纸条、派系特权都会把事件以"已知"排进日程;每天开门补盘时,对每个这样的、开始日在后天及以后的事件保证有一个盘口(窗口就是开始那天),开盘价按公开信息下的基础概率(不看冷却,每天有事件的概率取 35%),不因为已经排期而抬高——当晚价格才向 92% 靠拢,知道的人能赚到中间的差;押「是」算内幕单。游戏内验证:调试排一个 3 天后的已知停电,开盘出现"第 19 天:出现「停电」",是 0.03,线索"排期:第 19 天开始"。
|
||||
|
||||
- 高息理财(庞氏,Web3 "理财"页签,一个存档一次):选日息 2 / 4 / 6 / 8 / 10%,付 800 CRC 宣传费(Poinbase 账户)开张。每晚下层新存入 (300 + 15 × 天数) × (日息 / 4%)^1.5 × 声望系数 × 0.6–1.4 的 CRC,池子上限 6000 + 200 × 天数,每晚被取走 3%;利息先用新存入的付,不够从 Poinbase 账户补,补不上挤兑崩盘;每晚被举报概率 = 2% + 0.5 × 日息 + 4% × 池子占上限的比例(封顶 90%),被举报同样崩盘。崩盘或被举报:池子没收,记 FRAUD 1200(单件上限之外,按游戏罪证口径记一条),下层声望清零,报纸报道。随时可"卷走"(点两次确认):池子进 Poinbase 账户、污点全额,同样记罪证、清零声望。页面显示池子、昨晚存入、今晚利息、自己垫付的利息和"风声"(举报风险的三档提示)。
|
||||
- 复核(ops `research/ponzisim`,下层声望 50,每格 2000 局):日息越高越赚得快也越容易爆;开张第 40 天、日息 6%,熬 5 夜卷走平均净赚约 4000(崩盘概率 30%),熬 10 夜约 4800(53%),熬 20 夜约 2400(80%);日息 10% 熬 5 夜约 6800(41%),熬 20 夜约 900(89%)。每个选择的标准差和均值相当,"什么时候卷走"才是决策。
|
||||
- 游戏内验证:理财页签按日显示;4% 开张后一晚池子 372(昨晚存入 201、今晚利息 14.88);点两次卷走后 Poinbase CRC 4200 → 4572,污点 372;另一次 6% 开张过 4 夜被举报,池子 456 被没收,产品关闭,页面显示"每个存档只能开一次",晨间日志与新闻有记录。没有在游戏里验证:下层声望清零的实际数值(用游戏的 `SetReputation(0)`,没读回来看)、罪证数额的实际入账、付不出利息的挤兑路径(单元测试覆盖)、英文界面。
|
||||
|
||||
- 操纵检出(7.2 前半):Poinbase 主池上玩家自己的现货单会累计"推价幅度"(对数),每晚随价格回归衰减,预测盘线索里能看到。幅度超过 2% 后,价格盘押中且方向和推价一致、或 PSC 永续平仓盈利且方向一致,按幅度被查(25% + 6 × (幅度 − 2%),封顶 95%):预测盘本金和收益全部没收、永续盈利没收,收益的一半记 FRAUD(上限 400),永续账户冻结 3 天,报纸出一条调查新闻。把规则从最初设想的"单日推价 ≥ 15%"改成了 2% 起:manipsim 显示价格盘阈值离现价只有 3–10%,尾盘买 58 的成本就能赢上千,≥ 15% 的线形同虚设。
|
||||
- 复核(ops `research/manipsim`,第 30 天):先空后砸本身不赚——永续单边滑点加现货来回价差,砸盘 4000–20000 配 5000–20000 的空单平均净亏 66–4400,只有砸盘 4 万(推价 57%)配小空单才勉强为正;尾盘拉价格过价格盘阈值在没有检出时几乎稳赢(成本 40–125,净赚 570–1390,亏钱概率 ≈ 0),加检出后下注 ≤ 1000 平均只赚 100–240、亏钱概率 40–60%,下注 3000 平均亏 400–1500。
|
||||
- 游戏内验证:Poinbase 买 4000 CRC 的 PSC,推价累计 +15.1%,价格盘线索栏显示"你推价 +15.1%,易被查"。没有在游戏里验证:被查后的没收、新闻、永续冻结(单元测试覆盖预测盘判定;永续平仓的判定只有代码路径)。
|
||||
|
||||
#### 7.1
|
||||
|
||||
- Web3 页"预测"子页(游戏第 8 天起,Web3 治理社区已买下):每个盘口是一道是非题,开盘当天到窗口开始前可以买卖,窗口最后一天夜里结算;每天开门后补盘,同时开放 3–6 个,每天最多新开 2 个。资金走链上钱包的 CRC:买入、全部卖出都是合约调用,要在钱包上签名(和质押一样;买入的手续费在核对页选档、用 CRC 付,卖出用价值最高的币付);持仓记在签名的钱包名下,结算时兑付回这个钱包,同一盘口各钱包只能押同一边,持仓上限和内幕判定按盘口合计(拆到几个钱包躲不过)。污点与成本按花掉的价值比例随资金进持仓,赢的钱继承押注资金的污点比例,卖回时按比例退。
|
||||
- 盘口类型:新闻事件("出现某常规事件",先验 = 游戏掷骰规则:5 天后每天 50 / 35 / 25% 有事件,再按权重抽)、派系行动("某派系有行动开始",每天开始概率 6%,估计值)、水纯度(明天上层 / 下层水纯度 ≥ 阈值,先验精确)、PSC 价格(窗口最后一天夜间结算前的价格 ≥ 阈值,先验用价格过程的正态近似)。事件和派系行动靠夜间对比"昨晚生效的事件"得到当天新出现的;窗口里缺任何一天的记录(没睡觉结算)盘口作废、退回本金。
|
||||
- 界面不再出现"份":持仓直接写成本和"押中得多少"(每份押中兑付 1 信用点),盘口列表、右栏的各钱包持仓和买入预览都是这种写法,右栏另给"现在卖出得多少"。
|
||||
- 玩法打磨:
|
||||
- 界面:盘口行和右栏显示每份现价(是 / 否,等于概率)、持仓份数、均价、成本、押中得多少、现在卖出得多少;买入预览带均价。
|
||||
- 风险放大:单盘最大亏损改为 800 + 25 × 天数(第 30 天 1550),押错本金全亏;盘口价格每晚除了向合理概率靠拢还带随机噪声;买卖各 2%。
|
||||
- 消息反应:每晚还没封盘的盘口向"公开信息下的合理概率"靠拢一半(报纸上已排期的事件 / 派系行动 → 92%,进行中或冷却中 → 2%,行情盘按最新价格,gas 盘按周期,CRA 盘按补贴池水位,矿机时代按预警),再加 logit 噪声 0.35。价格在夜里才反应,白天看到消息的人可以抢在前面买、涨价后卖,不必持有到结算;开盘到窗口开始的天数从 1–2 天改为 1–3 天,让反应有时间发生。
|
||||
- 线索栏:盘口面板列出和它有关的已知信息:排期(传闻、派系特权)、事件进行中或冷却、派系行动进行中、减半日与已排期的镇压 / 停电、价格锚、近几天 gas、CRA 补贴池水位和每晚消耗、矿机时代预告、手里的内幕消息。
|
||||
- 新盘口:gas 指数(明天 ≥ 阈值,7 天周期,先验是七个相位的平均,周期是玩家看得出来的);CRA 预警(补贴池每晚被消耗,归零必预警,质押越多越快);矿机时代(预告前按 50–90 天均匀,预告后落在 4–7 天里,要 day + 4 ≥ 50 才开,避免泄露)。CRA 和矿机时代读 mod 状态,所以预测结算挪到夜间结算的最后(行情盘、gas 盘用结算开始时记下的收盘数据)。
|
||||
- 玩家能推动的:PSC 价格盘能被自己的大单推动(操纵检出放在 7.2);CRA 盘靠质押量推动补贴池消耗。
|
||||
- 情报页(Web3 黑市解锁且声望 ≥ 20 才出现):局势简报(120 CRT)列出五个势力值和每个派系按游戏阈值现在能发起的行动,派系行动已排期 / 进行中的也标出,10% 概率是假情报(数值是编的);内幕消息只卖已经定了的盘口(排进日程的派系行动、矿机时代日子),三档准确率约 60 / 80 / 95%,价格是盘口最大亏损的 1 / 2.5 / 5%(CRT),一成是假情报(说的和真相相反);买了消息再押同一边算内幕单。付款是 CRT 的合约调用,要签名,花掉的币带走对应比例的污点。
|
||||
- 复核(predsim v2):不知情随机押仍是负期望;低先验盘口买消息基本亏;中先验盘口(20–50%)高档消息下注 400 以上才赚,低档消息几乎都是亏的陷阱;单盘输赢在上千,亏钱的概率可观。
|
||||
- 定价:LMSR,初始价 = 先验,单盘系统最大亏损 = 300 + 10 × 天数,流动性参数由它反推;买卖各收 2%;单人单盘份额上限 = 最大亏损 × 3;一个盘口只持有一边。
|
||||
- 内幕:下注时这个事件(或派系行动)已经以"玩家看得到"的形式排进日程(传闻纸条、派系特权),而且落在窗口里,押「是」算内幕单。内幕持仓达到份额上限的 40% 后,结算时 50% 概率被查:只退本金,收益的一半(上限 400)记 FRAUD 罪证。情报顾客没接。
|
||||
- 复核(ops `research/predsim`):不知情随机押期望为负;谨慎的内幕(压在查处线下)在低先验盘口一盘净赚 270–520(第 30 天最大亏损 600),买满上限的期望反而更低。行情先验和真实 `Market` 过程的蒙特卡洛对得上(单元测试,误差 < 4%)。
|
||||
- 游戏内验证:新开盘口列表显示问题、先验、持仓;在 PLEDGER 上签名买入 100 CRC 得 117–424 份并涨价(钱包 CRC 1000 → 899,含 1.5 手续费)、签名全部卖出收回 96.08(扣 2%);调试推进几天后押中的纯度盘兑付 117 回到钱包(CRC 995 → 1,012),晨间日志"预测押中";此前用 Poinbase 账户的版本还验证过价格盘兑付 199;一个真实的革命军行动被观测到并结算为"是";没押的盘口也进"最近结果"。没有在游戏里验证:常规新闻事件盘口的自然结算(本次测试存档里没碰上)、作废、内幕判定与被查、手册文字、英文界面。派系每天 6% 的先验没有真实数据校准。
|
||||
- 单元测试 11647 通过(含多钱包持仓:各回各的钱包、限额与内幕合计;消息反应、情报、gas / CRA / 矿机时代先验)。
|
||||
- 游戏内验证(玩法打磨):价格显示、情报页、局势简报(真实读到安保行动已排期等)、三档内幕消息购买与签名、线索栏显示情报与矿机时代预告、买「是」押矿机时代后结算兑付 945。没有在游戏里验证:夜间消息反应的实际价格变化(只有单元测试,夜里跑过没报错)、gas / CRA 盘口的结算(只有单元测试)、报纸排期引起的 92% 靠拢、假情报、被查、英文界面。
|
||||
|
||||
### 第六阶段:高收益与高风险(进行中)
|
||||
|
||||
- RatDigg 矿机(M1 / M2 / M3,11,000 / 27,000 / 72,000,50 / 120 / 300 H,60 / 110 / 220 kJ/天):独立的 Machinery,窗口里有电池槽、模块槽(和矿架同一套效果与上限)、修理槽,没有显卡槽;夜间和矿架一样先从电池扣电、有电才挖,算入全网算力。损耗每天 0.8,暴毙系数 0.5;没有外观、没有真假。暴毙后成"损坏的矿机"(残值 15%),往修理槽按顺序放电子元件修好(M1:4 普通 + 1 稀有;M2:2 稀有;M3:1 超科技 + 1 稀有,约机价的 4%),修好健康 −20。新画了三张像素图(M1 绿、M2 蓝、M3 金的指示灯与风扇轴心)。
|
||||
- 来源只在 Web3 黑市:新增商家类型"矿机商",声望 ≥ 40 起每周 25% 出现,一次一台,70% 全新、其余二手(健康 40–85,价格按健康折算);型号按声望放开(M1 40、M2 60、M3 80),出现权重 1 / 0.6 / 0.4;价格系数同尖端店铺 0.85–1.00。可以在"卖货"页转手,损坏的不能上架。
|
||||
- "矿机时代":第 50–90 天之间随机一天(存档接入得晚则至少留出预兆天数),提前 4–7 天上报纸预告,到点 NPC 矿工耗电效率翻倍(`NpcKj` 2.4 → 1.2),永久。NPC 愿意挖得更久,均衡算力上升,显卡矿工的收益被摊薄。
|
||||
- 复核(ops `research/asicsim`,真实 Network 与 Market,每组 150 局,玩家另有一个 20 H 的矿架,电费按电网价 1.5):买入后累计回本——M1 第 20 天买 20 天、第 60 天买 22 天(有矿机时代 28 天)、第 100 天买 32 天(有矿机时代 61 天);M2 21 / 23 / 34 天(有时代 28 / 59);M3 26 / 28 / 42 天(有时代 37 / 65)。矿机时代之后一台 M1 每天净赚约 140–210,仍然为正。M3 要 7.2 万现金和声望 80,实际上早期买不起。
|
||||
- 游戏内验证:三台矿机可以造出、放进柜台、打开窗口(电池 / 模块 / 修理三个面板);放自充电池后夜里 M1 挖出 11.83 PSC(= 50/410 × 100 × 0.97);手动标记损坏后,修理槽只收这一步需要的元件(M2 拒收普通元件,M1 收下 4 个普通元件进入下一步,M3 收下超科技元件进入下一步),M2 放两个稀有元件后"修好了,健康 80";"矿机时代"调试入口:第 3 天日志"矿机时代到来";黑市"矿机商"货架:「RatDigg M1 矿机 矿机 全新 剩 1 件 11148 信用点等值」带图标。没有在游戏里验证:真实暴毙(只有单元测试)、报纸上的两条矿机时代新闻、从黑市买下矿机后的收货、模块对矿机的效果。
|
||||
- Poinbase 永续合约(Poinbase 页"永续"子页):PSC-PERP 最高 5 倍、单仓名义上限 20000,SPARK-PERP 最高 3 倍、上限 5000;保证金用 Poinbase 账户的 CRC,一个品种一个净仓位(同品种不能多空同开),托管账户不用签名。成交价按名义价值占现货池深的比例滑点(深度倍数 3:名义 5000、池深 5 万时单边约 3.3%),开平仓各收 0.1%。
|
||||
- 标记价 = 当日均价(开盘价与收盘价的平均,SPARK 取当天价),强平只在夜间检查:权益低于名义价值的 10% 时强平,保证金没了,剩余权益(扣 2% 强平费后)进保险基金。每晚资金费 = 0.1 × (标记价 / 7 日均价 − 1),上下限 ±0.3%,价格偏高时多头付空头。开仓时按现价算权益若已低于强平线再加 2%,直接拒绝(滑点太大,开了就是被强平)。
|
||||
- 保险基金初始 10000,每晚 +150,手续费的 30% 进基金;NPC 在大行情(标记价日涨跌超过 6%)里穿仓会按涨跌幅的平方抽走基金(SPARK 崩盘能抽干)。基金见底时盈利仓位被自动减仓,少拿一半盈利。强平穿仓的缺口先由基金垫,不够的记成玩家的欠款。
|
||||
- 欠款每天计息 2%,每晚先用 Poinbase 账户里的 CRC 还;有欠款不能开仓、不能出金;7 天没还清,用游戏自己的没收接口(`FindRepoItems` / `GetAllRepoEligibleItems`,和房贷逾期同一套,不碰放贷人 Lou)没收店里物品抵债,抵不够的核销,永续账户拉黑 30 天。污点随保证金进仓位,平仓时按剩下的比例退回,盈利是干净的新币。
|
||||
- 校准(ops `research/perpsim`,真实 Market 和 PerpBook,120 天,起始 3000):没有滑点时"看 7 日均线反向做"+75%、"跟着资金费走"+46%、知道价格锚的上限 +148%——PSC 每晚向锚回归 15% 的规律被杠杆放大,资金费在这个方向上反而补贴了回归的一边(价格偏高时空头收钱)。加滑点后深度倍数 3:看均线 +19%、跟着资金费 +26%、上限 +88%,随机交易 −66%、5 倍死扛 −72%;资金费系数 0.03–0.25 几乎没有影响。
|
||||
- 游戏内验证:PSC 5× 满额(名义 20000,滑点 13%)开仓当场强平价 101 高于现价 100,因此加了开仓校验;SPARK 多头强平后日志"SPARK 多被强平,保证金 1,666 没了";砸 SPARK 两次、提光账户现金后:欠款 2,627,每天 +2%(2,679 … 2,958),第 7 天夜里没收物品抵 3,018,欠款清零;PSC 强平的剩余权益进基金,基金见底时盈利仓位被自动减仓的路径只有单元测试。没有在游戏里验证:没收单物品(没在探查里找到,可能柜台满了)、资金费真实收付、拉黑 30 天。
|
||||
- CRA 质押(Web3 页"质押"子页):把 CRA 质押进革命军质押池,日息 0.5%(补贴池告急降到 0.2%),利息并入本金;取出要先申请,4 天后自动回到质押时的钱包,等待期间不计息。每个钱包一个仓位,污点与成本随币存入、按比例随币取出;仓位和解锁队列在质押页列出。质押、申请取出都是合约调用,要在钱包上签名;申请取出不花币,手续费用钱包里价值最高的币付。补贴池按玩家质押量一并消耗。
|
||||
- 预兆新闻:螺旋预兆出现的那晚上报纸("质押池传出异动"),补贴池告急降息时再上一条。
|
||||
- 平衡代币 SPARK:起始价 10 信用点,日波动 8%,每晚向 10 回归 3%,范围 3–30;革命军袭击上层 +15%,下层动荡 −10%;CRA 死亡螺旋三天里按螺旋前价格的 ×0.8 / ×0.3 / ×0.05 暴跌。可以和 CRA 按价格互相铸销,手续费 0.3%,也是合约调用。钱包的币种里多了 SPARK。
|
||||
- 游戏内验证:质押 400 CRA(手续费 1.5 CRA),申请取出 100(第 5 天),铸造 100 CRA 得 9.97 SPARK;第 6 天夜里 100 CRA 回到主钱包,利息 +1.5(300 × 0.5%);触发螺旋预兆后三晚:CRA 0.85 → … → 0.02,SPARK 5.94 → 0.371,质押仓位的数量继续涨(利息)但价格归零。没有在游戏里验证:报纸上的预兆新闻(没有打开报纸)、补贴池自然见底降息。
|
||||
- 夜间结算此前在测试存档里没有跑起来:调试面板的"CRA + PSC"只给币,不会解锁 Web3,夜间逻辑要先解锁("Black market +50 rep")。
|
||||
|
||||
### 第五阶段:硬件钱包(进行中)
|
||||
|
||||
- 硬件钱包 PLEDGER:终端顶栏"钱包"打开的独立窗口。像素画的圆角石墨机身、黑色屏幕边框、浅色墨水屏,下沿两个物理按键(左 × 拒绝 / 返回,右 ✓ 下一步,签名要按住 1.2 秒,显示游戏自带的按住圆环)。屏幕页:主钱包(地址、余额、合计、污点)、发送、核对、交易、已确认。
|
||||
- 链上地址改成 "0x" + 6 位 + 2 位校验位(FNV-1a 高 8 位)。输错一位几乎都被拦下("地址校验失败"),约 1/256 碰巧合法;合法但没人用的地址,核对页提示"没有交易记录",签名后币转不回来。旧存档的商家和收款地址载入时换成新格式。
|
||||
- 付款改成账单:黑市现货、商家订单、上架费、改价费、批量上架、混币器、Ponero 兑换在终端开账单(收款地址、币种、金额),"打开钱包转账"在钱包里预填币种和金额,地址要手输。付给有账单的地址才执行;币种不对、金额不足在发送页拦下;多付的部分不退;对有往来但没有账单的地址拒绝发送。账单不随切换终端页面作废,可以手动作废。
|
||||
- DEX 兑换改成合约调用:在终端点买入 / 卖出后钱包弹出签名请求,按住 ✓ 签名后才成交,× 拒绝。Poinbase 是托管账户,仍直接成交。
|
||||
- 签名后的动画:签名中 → 已广播(内存池)→ 打包进区块 #N → 确认 1/3、2/3、3/3,约 5 秒,可跳过;窗口关着也会走完。区块高度存档。
|
||||
- 游戏内验证:DEX 10 CRT 兑 PSC(签名 → 确认 → CRT 4000 → 3990);黑市现货手枪:输错末位被校验位拦下,改对后付 156 CRT,库存 3 → 2,货进储藏区,污点按比例减少;向 0x12345699 转 1 CRT,提示转不回来,余额减 1;Ponero 兑换 10 PSC 得 18.8 Ponero,当天额度用完。没有在游戏里验证:混币器账单(测试存档没解锁混币器)、商家订单、上架 / 改价费账单(代码路径和现货相同)。
|
||||
- 多钱包:每个硬件钱包的余额、污点、成本、冻结各算各的。终端新增"钱包"页:列出全部钱包(名称、地址、估值、污点),"打开"弹出这个钱包自己的 PLEDGER 窗口(几台可以同时开),"连接"设为当前钱包。Web3 页的交易、黑市、混币器用当前钱包;用币付款的顾客、挖矿收益进当前钱包;订单退款、出售回款、混币提回回到当初付款的钱包。账单可以用任何一台钱包付。钱包之间转账走签名,污点按比例跟着走。
|
||||
- Poinbase 拆成托管账户:银行存入进 Poinbase,出金审查只看 Poinbase 账户的污点;Poinbase 页"提到当前钱包"直接转,不用签名;钱包充值要转到 Poinbase 的充值地址(页面上显示),只收 CRC 和 PSC。
|
||||
- PLEDGER 硬件钱包(物品):和游戏的升级材料一样,拖到交易终端上用掉,钱包 +1,最多 5 个。杰克逊博士进货时(钱包没满)50% 上一个,价值 240,正品;Web3 黑市平台现货每周 50% 上 1–2 个,150–180,其中 20% 被投毒。外观和说明完全一样。被投毒的钱包币的总价值到 3000 起,每晚有概率被转空(1/7 起,按价值线性升到 20000 时当晚必转),晨间日志只写"钱包 n:币被转走了"。
|
||||
- 被投毒的钱包按期望天数算:门槛(3000)处期望 7 天,按价值线性降到 20000 处 1 天,每晚概率 = 1 / 期望天数(中间值期望 4 天、每晚 25%,模拟 4000 次平均 4 天)。
|
||||
- 复制粘贴:终端账单的收款地址、Poinbase 充值地址、钱包页每个钱包、PLEDGER 主页的本钱包地址都有"复制";PLEDGER 发送页收款地址旁有"粘贴"。用的是系统剪贴板。
|
||||
- PLEDGER 主页余额改成三列(币种 | 数量 | 估值)右对齐,五种币全部显示(含 0,冻结的另注);点一行选中,整行反色高亮,发送时默认用选中的币。
|
||||
- 钱包页:每个钱包可以改名(留空恢复默认,最长 16 字),名字在终端和 PLEDGER 上都用;非主钱包可以销毁(点两次确认,钱包里还有币时不让销毁)。钱包编号固定,销毁别的钱包后名字不会错位。
|
||||
- 游戏内验证(这一轮):复制钱包 3 地址后在主钱包发送页粘贴,地址正确;选中 CRT 行高亮,进发送页默认 CRT;向钱包 3 转 1 CRT 后点销毁被拦下;钱包 2 二次确认后销毁,钱包 3 仍叫"钱包 3";钱包 2 改名为 cold,终端与 PLEDGER 都显示新名字;三列余额对齐。PLEDGER 上名字被标题样式转成大写,已改成普通粗体(编译通过,没重进游戏看)。没有验证:游戏输入框里直接 Ctrl+V。
|
||||
- 转账手续费档位(核对页选 慢 / 普通 / 快):0.5 / 1.5 / 4 信用点等值,用转出的币扣(DEX 签名用付出的币);需要的确认数随金额:3 次,≥ 2000 时 6 次,≥ 10000 时 12 次,动画随之变长。
|
||||
- Gas 价格指数:7 天一个周期正弦涨跌(0.5×–1.5×),每天再乘 1 ± 15% 随机波动,夜间结算算出第二天的值;手续费 = 档位基础价 × gas(拥堵时再 ×4),核对页显示"Gas ×n"。游戏内验证:过一夜 gas ×1.34,普通档手续费 1.5 → 2.01 信用点。
|
||||
- 网络拥堵:每晚 12% 开始,持续 1–2 天,上报纸;拥堵时手续费 ×4,普通档确认 ×2 慢、慢档 ×3.5 慢,慢档 30% 被挤出内存池(未成交,手续费照扣,账单留着可以重付)。PLEDGER 主页和核对页显示"网络拥堵"。
|
||||
- 地址投毒:每笔转给外部地址的转账有 35% 被盯上,1–2 天后钱包收到一笔来自相似地址的 0 币转入(前 3 位和末 2 位校验位一样,缩写完全相同)。PLEDGER 发送页新增"最近"列表(← 转入 / → 转出,缩写地址),点一下填入地址,投毒地址混在里面;核对页对有往来的地址显示"有往来记录",投毒地址也会显示。
|
||||
- 剪贴板木马:被投毒的钱包上点"粘贴",30% 把地址换成相似地址(和一次转空并存)。
|
||||
- 钓鱼公告:每晚 5%,报纸上"Poinbase 充值地址迁移"或黑市论坛上"混币器新地址",给的是没人用的地址,转进去就没了。
|
||||
- PLEDGER 屏上的选择按钮(币种、手续费档位):选中的一个白底黑框黑字,四角带取景框角标,不再用方括号。
|
||||
- 游戏内验证(第三批):手续费 1.5 CRT 扣除;拥堵时核对页手续费 ×4、慢档提示;最近列表出现投毒的"← 0x123…99 0 PSC",点它进核对页显示真实地址 0x12342499 与"有往来记录",签名后币转进投毒地址;慢档连续 13 次里 4 次"未成交",手续费照扣;论坛出现钓鱼帖;选中样式截图看过。没有在游戏里看到:报纸上的拥堵 / 钓鱼新闻(F9 面板那次没打开,代码走的是已用过的新闻接口)、剪贴板木马(只有被投毒的钱包触发,没专门测)、大额转账的 6 / 12 次确认动画(单元测试覆盖确认数)。
|
||||
- 被标记的钱包转出可追踪的币(CRC、PSC、CRT、CRA),收款钱包也被标记(含 Poinbase 账户);Ponero 不带标记。之前分成多钱包后,混币器在制裁期提回的币转进 Poinbase 就不再被标记,出金审查少了 30% 的加成。
|
||||
- 多钱包分流复核(ops `research/walletsim`,真实 Wallet / Exchange 类,每种做法 300 局 × 60 天):把干净和脏收入分到两个钱包、每天按 9.9% 污点比例往 Poinbase 掺脏币,可以零风险每天洗出约 36 污点(60 天约 2200),上限约等于干净出金量的 11%;同样的进账用单钱包出金能洗出更多污点(2400–4100),但会被没收、脏币多时会记罪证。没有干净收入时分流洗不出任何东西;而阶段 5 之前就能做到的"银行存入干净信用点稀释"60 天洗出 1350。结论:多钱包没有打开新的大口子,零风险的涓流来自 10% 以下审查项为 0 的这道坎,阶段 5 之前就存在。
|
||||
- 阶段 5 收尾补测(游戏内):用鼠标把两件硬件钱包(一正一毒)拖到终端上,各消耗一件、钱包页添加;杰克逊上货时出现了硬件钱包(需要多次触发,柜台满时会写"柜台已满");混币器账单、商家订单(模组,托管,订单页显示在途)、上架费、改价费(40 → 36)四种账单都在钱包里手输地址、签名后生效;夜里自然触发了地址投毒(刚付过的商家 0x149caf58 → 相似地址 0x149ff558 转入 0 币);被投毒的钱包上连续粘贴 10 次,有 5 次地址被换成相似地址(前 3 位与末位相同)。没有在游戏里验证:杰克逊柜台上钱包的标价(探查通道看不到价格,只有物品没有标价标签)、被标记状态传播(只有单元测试)、报纸上的拥堵 / 钓鱼新闻(夜里没抽到)、Ctrl+V 直接粘贴到输入框。调试面板新增"Give terminal",调试解锁同时解锁混币器。
|
||||
- 存档不兼容旧版:链上的币归到新建的主钱包,Poinbase 账户从 0 开始。
|
||||
- 游戏内验证(多钱包):两件硬件钱包(一正一投毒)作用于终端,钱包页出现钱包 2、钱包 3,标记看不出来;同时打开两台 PLEDGER;主钱包向钱包 3 转 100 PSC,核对页显示"自己的钱包:钱包 3",污点 5000 按 10000/16000 带走 3125;过一夜钱包 3 被转空(约 9393),晨间日志有记录;银行存入 500 进 Poinbase,提 200 CRC 到主钱包,再从主钱包向充值地址转 100 CRC,Poinbase 300 → 400,带过去污点 31。商城平台现货出现硬件钱包(158)。没有在游戏里验证:用鼠标拖拽(用探查通道执行了同一个"物品作用于物品"接口)、杰克逊柜台上的钱包和它的标价、Poinbase 空账户和"账户污点比例"两处改字(已编译,没重进游戏看)。
|
||||
|
||||
### 第四阶段:Web3 黑市与 Ponero(进行中)
|
||||
|
||||
- 人脉网络新增"Web3 黑市"(前置:Web3 治理社区,1500):黑市派系在链上的实体;放在终端 Web3 页的"黑市"子页里,需要黑市声望 ≥ 10,镇压期间下线。
|
||||
- 现货柜台:每周刷新一批违禁品(游戏已有的 32 种,低 / 中 / 高三档随声望 10 / 40 / 80 放开;件数 4 + 声望/40),价格 = 游戏基础价 × 1.3,只收 PSC / CRT / CRA / Ponero,不收 CRC。付出去的币连同按比例的污点留在卖家那边,货放进储藏区,不带赃物标签。
|
||||
- Ponero 兑换处(声望 ≥ 30):任意币兑入 Ponero 时这部分价值的污点留在原地,兑入、兑出各收 10%,每天额度 600 信用点(收尾核算后由 8% / 1000 调整);Ponero 价 = PSC × 0.5。从 Ponero 兑出的币在出金审查里按"刚出混币器"加重。
|
||||
- 游戏内验证:声望 75 时上架 5 种;用 CRT 买一把左轮 312 点,余额 3000 → 2688,污点 2000 → 1875(按付款占钱包的比例);5 PSC 兑入得 9.2 Ponero(500 × 0.92 / 50),当天额度剩 500。
|
||||
- 订单:黑市页新增"订单"和"我的订单与情报"。目录每周刷新,4 个卖家(成交数、好评率公开,15% 是骗子,多半是新号,也有刷过好评的老号),价格 = 基础价 × 0.85。托管多付 5%,收货后放款,卖家跑路时退款(污点与成本一并还回,不能借退款洗钱);提前放款再打九折,只有成交 ≥ 30 的卖家接受,骗子拿钱就跑。
|
||||
- 配送:送货上门 3 天,到货后开店时快递员作为顾客上门,对话结束把货放进储藏区;死投点 2 天,到货后晚上去垃圾场,货进外出背包。上门被截获 8%,死投 3%,死投另有 12% 被别人先挖走;镇压期间到期顺延、截获 +15%。
|
||||
- 平台跑路:每晚概率 0.2% + 在途款项每万信用点 0.4%(封顶 5%),跑路后在途款项归零、目录与现货清空、入口关闭 10 天。论坛情报:骗子卖家有一半概率被人点名,跑路风险升高时出现提币变慢的帖子。
|
||||
- 游戏内验证:下单后在途显示在"我的订单";过夜到期,两单到货,一单骗子卖家托管退款(CRT +143,污点 +57);快递员对话走完,货进储藏区,快递员自动离开。没有在游戏里验证:死投点取货(要去垃圾场)、平台跑路与截获的实际触发(只有单元测试)。
|
||||
- 商城改成货架式:每行 4 张商品卡(游戏物品贴图、名称、类别、库存或卖家、价格、按钮);删掉死投点,只剩送货上门;货架上除违禁品外偶尔有高科技物品(声望 ≥ 40,加价 50%)和显卡(加价 20%,20% 是假卡)。
|
||||
- 界面不放说明文字:银行、交易、混币器、黑市、Ponero 的规则说明都移进新物品"Web3 手册"(购买 Web3 治理社区时一并交付)。
|
||||
- 游戏内验证:货架显示贴图与成色,用 CRT 买一张 RTX 60(232)进储藏区。
|
||||
- 第三批:执法蜜罐——每晚有概率接管平台(1% + 治安声望 × 0.04%,封顶 6%),持续 6 天,期间下的单和之后 4 天到期记罪证(违禁品 / 高科技记 `CONTRABAND_TRAFFICKING`,显卡记 `FENCING`,金额 = 货款,上限 400),论坛出现"最近太顺了"。卖家落网——近期成交的卖家每晚 0.8% 被抓,他留存的订单 4 天后连累买家,论坛有传闻。
|
||||
- 受控交付:被截获的包裹有 35% 变成执法人员上门:快递员神色异常,出现"签收。/不收,退回去。"两个选项;签收当场记罪证并查封,拒签只损失货款。
|
||||
- 挖矿报告并进 Web3 页的"挖矿"子页,终端顶栏不再有"报告"。
|
||||
- 游戏内验证:受控交付的对话与两个选项显示,拒签后快递员离开、下一位顾客进来。没在游戏里验证:签收的罪证、蜜罐与落网的夜间追查(只有单元测试)。
|
||||
|
||||
- 货架重做:违禁品池只留能转手的货(枪械、钥匙卡、密码解序器芯片、爆炸物),弹药、毒品、药品、化学品、种子全部移除;高科技物品池换成矿机能用的东西(7 种系统模组、能量电池、能量阵列、高级模组提取器、矿架);显卡与高科技各占 30%,高科技不再需要中档声望。
|
||||
- 玩家出售:黑市页新增"出售"子页。储藏区里的违禁品、高科技物品和显卡做成货架,选标价倍率 0.6–1.8(相对参考价;显卡按标称型号与成色)上架,收 5% 上架费。每晚按期望天数成交:≤0.9 倍 1 天,1.0 倍 2 天,1.8 倍 14 天,之间插值。成交扣 8% 抽成,货款托管 3 天后以 CRT 进钱包。货款带污点的概率和比例随倍率从 20%/20% 涨到 90%/80%。
|
||||
- 出售的风险:假卡有 50% 被买家看穿退货,好评 −10(好评影响成交速度,每笔成交 +1);平台跑路时上架的货和未放款的货款都没了;蜜罐期间成交的货款和近期买家落网会被追查记罪证;镇压期间平台不成交。"我的订单与情报"页多出"我的上架",可以撤下。
|
||||
- 游戏内验证(全部商家逐家点开截图):21 家商家(18 类 + 大宗 + 尖端店铺 + 2 位个人卖家)的货架都显示正常;尖端店铺卖全新 RTX 90(5139)和超科技储藏区(10265);个人卖家混着药、模组、水培、显卡,价格各异。
|
||||
- 游戏内验证:货架显示显卡、模组、能量电池;买一张卡后出售页列出储藏区里的货,上架(标价 400,上架费 20),过夜成交(货款 368),3 天后到账(CRT 2804 → 3172,这次随机没带污点)。没有在游戏里验证:假卡退货、跑路时的出售损失(只有单元测试)。
|
||||
|
||||
- 收尾核算(`research/sim/bm_econ.py`,按 Tuning 常量算期望):Ponero 来回 15.4%,与混币器洗掉 80% 污点的 15–18% 相当,但当天完成、清得彻底、不受制裁,所以手续费 8% → 10%(来回 19%),日额度 1000 → 600(日额度按钱包污点占比估,约够清掉稳态的污点流入,后期会成为瓶颈);出售的最优倍率取决于玩家的资金机会成本:每天 1% 时 ×1.8,2–3% 时 ×1.5,倍率不是越高越好;订单:托管期望净 +0.02、提前放款 +0.07(现货 −0.30),所以订单是便宜进货,不是赚钱路线;订单进货再挂高价出售的套利每件约 +0.13–0.18(20 天一轮,资金占用),量小,暂不限制上架数。
|
||||
- 订单改成商家货架(用户意见):黑市页"订单"改名"商家",每周从 6 种类型里抽 5 家(全新矿卡经销商、二手矿卡贩子、模组高科技、军火、证件芯片、药物),另有 25% 的周出现一家大宗商家(库存 10–25 件、价格系数 0.55–0.75、送货 6 天)。每家有自己的价格系数(订单价 = 基础价 × 系数,一般 0.70–0.95,全新卡 0.85–1.00,二手卡 0.65–0.90),每家 4 种货、库存 3–6 件。一次订 5 件以上 95 折、10 件以上 9 折。界面:件数按钮 ×1 / ×5 / ×10,商家按钮,所选商家的货架。药物(药片、梦尘、管制化学品)只在药物商家和大宗商家出现,也能转手出售。每周货架总值在游戏里抽样 60 周平均 13.2k(目标 1.4 万)。
|
||||
- 商家类型扩到 18 种 + 大宗(用户意见,对照游戏的物品目录和玩家职业):全新矿卡经销商、二手矿卡贩子、矿架与能源、模组、军火(枪、手雷、炸药、刀具、电击枪)、枪匠配件(枪械配件、3D 打印芯片与模组、枪械零件)、证件芯片、药物(药片、注射器、血袋、手术工具)、化学品(化学用品、助熔剂、化学设备模组、量筒试剂瓶)、酿酒(酵母、荧光莓、啤酒、酒瓶)、水培农场(种子、水培模组、植物分析仪)、养殖(鱼卵、鱼子酱、循环水养殖系统、血清、屠宰机)、矿工(矿石、金属锭、电子元件、拾荒扫描仪)、水务(滤水、净水、储水、检测)、仓储(走私暗格、储藏区扩建、军用背包)、工具(涡轮增压器、等离子切割机、X 射线扫描仪、心智重编程器)、奢侈品(香水、精华液、香烟)。每周 7 家:2 家从矿卡 / 矿架 / 模组 4 类里抽(保证矿工路线总有货),其余 5 家从其余类型里抽;每家 3 种货,库存 2–5 件,单件基础价超过 4000 的不上。游戏里抽样 60 周货架总值平均 13.2k(目标 1.4 万)。药物改成并入药物商家,现货柜台的货不变。所有货都能转手出售。
|
||||
- 尖端店铺与个人卖家(用户意见):贵货(单件基础价 ≥ 2000:超科技涡轮增压器、超科技储藏区、心智重编程器、顶级显卡等)不再被一刀切掉,改由"尖端店铺"卖:每周只有 15% 的概率出现,2 种货、库存 1–2 件、价格系数 0.85–1.00、送货 5 天;顶级全新显卡也在这里。个人卖家:每周固定 2 位,什么都卖(可能是药、模组、显卡、仍有 10% 混进贵货),每件价格系数各自随机 0.50–1.20(捡漏或被宰),库存 1–2 件,是骗子的概率 25%,都是新号所以只接受托管。常规商家仍只卖基础价 ≤ 4000 的货。
|
||||
- 黑市标签整理(用户意见):原来的"现货柜台 / 商家 / 出售 / 我的订单与情报 / Ponero 兑换处"改成三个对称的标签"买货 / 卖货 / 订单"。买货页里平台现货是第一家卖家("[平台] 0x…",立即到货,选它时不显示托管 / 提前放款),后面是各商家,件数按钮 ×1 / ×5 / ×10 现货也适用(一次买多件走一次付款确认);论坛情报放到买货页最下面;订单页分"买入"(订单)和"卖出"(上架、改价、撤下)上下两块。Ponero 不再是黑市里的标签:并进 Web3"交易"页的右栏,作为一个带"[匿名币]"标签的通用兑换块(选 PSC / CRT / CRA,兑入 / 兑出,要黑市声望,仍有每日额度和手输地址确认)。游戏内验证:新的三个标签和平台现货货架、订单页、交易页的 Ponero 块,兑入进入付款确认。
|
||||
- 定价改成直接输价格(用户意见):点货架上的"上架"或"我的订单"里的"改价",出现"设定标价"页,显示参考价(真实价)和输入框;×0.6–×1.8 档位只是帮忙把价格填进输入框,也可以手输整数,输入后显示"标价 83(×1.38)";价格要在参考价的 0.6–1.8 倍之间(显示可输范围),确定后走付款确认(上架费 5% / 改价费 2% 按新标价算)。成交速度和货款污点都按 标价 ÷ 参考价 的实际比例连续计算(不再只有档位)。"我的订单"里每件上架的货显示"参考 60 标价 83(×1.38)",下面是"改价"和"撤下"。出售页顶上的档位按钮保留,作为默认倍率(预填价格、"全部上架"用)。游戏内验证:档位填价(×1.5 → 90)、手输 83(×1.38,上架费 5)、范围外(200)被拒并提示 36–108。
|
||||
- 自己的储藏区和背包不再出现在可上架的货里,有内容的容器也不行(之前储藏区(扩建)会被列出来,上架会把里面的东西一起带走)。
|
||||
- 上架后可以改价(用户意见):"我的订单与情报"页每件上架的货下面一排倍率按钮(0.6–1.8,当前的带方括号)和"撤下",点倍率先走付款确认(改价费 2%,`BmRepriceFee`,手输平台地址),标价按参考价重算,成交概率按新倍率走,上架日不变。游戏内验证:0.6 倍的 RTX 70 改成 ×1.2,改价费 12,标价 600。蜜罐基础概率维持 1%(模拟里进取策略罪证 ≥ 300 约 48 天,用户认为可接受)。
|
||||
- 追查调整(经济模拟后):同一晚到期的追查按来源合成一次事件,记入货款的 40%(`BmTrapShare`),同一次蜜罐 / 落网累计最多 400(`BmTrapWindowCap`);没收到货的订单(骗子退款、被截获、跑路、拒签、被查封)取消对应追查。原来每单各记一次、每晚上限 400,一个蜜罐窗口能连续记几千,模拟里一局 120 天几乎一直在罪证线以上。
|
||||
- 手输收款地址(用户意见):Web3 里的付款与转账——黑市现货、商家下单、上架费、混币器存入、Ponero 兑换——点下去先出"确认付款"页,显示摘要和收款地址(商家是名字里的 0x… ,平台、混币器、Ponero 兑换处各有自己的随机地址,存档保存),要手输地址才放款,不分大小写,输错提示"地址不符,没有付款",可取消。DEX 兑换和银行存取不加(没有收款方);交易所的转账等阶段 5 多钱包时再接同一个确认页。游戏内验证:现货买超频模组,输错一位被拒、输对成交;Ponero 兑换处进入确认页。
|
||||
- 商家名用随机哈希匿名,前面用方括号标类型(用户意见,试过每类型 10 个主题店名后撤回):如 "[全新矿卡] 0xdf9ec7";选中的商家按钮前有 "> "。
|
||||
- 每周货架总值放宽到 2 万左右(用户意见):库存范围 2–5 → 2–6,游戏里抽样 60 周平均 22.2k,尖端店铺出现概率保持 15% 不变,不靠它拉高周转量。
|
||||
- 同时上架最多 10 件(用户意见),出售页显示"上架 n/10",超出时提示。
|
||||
- 出售:货款污点随近 7 天成交额加重(成交额达 1.4 万时概率与比例各加 30%);出售页加"全部上架"按钮。套利核算(`bm_econ.py`,商家系数均值 0.825 再加批量折扣):普通商家提前放款进货 + ×1.5 出售每件约 +21%,大宗商家约 +33%,一周可买的货约 1.3 万,带污点的货款约够吃满 Ponero 日额度。
|
||||
- 调整(用户意见):Ponero 手续费 10% → 6%(一进一出约 12%),日额度 600 → 1000;混币器每轮手续费 4% → 3%。黑市货架上的显卡有 15% 是全新卡(成色 100,封条完好,不会是假卡),标签显示"全新"。全新卡只有单元测试,没有在游戏里见过。
|
||||
- 收尾验证(游戏内):黑市每周刷新(第 8 天自动刷出 5 种现货、8 种订单目录);蜜罐追查到期记罪证 300;假卡上架 8 件,有一件被看穿退货(好评下降);其余成交后到账,其中一笔带污点;受控交付选"签收。"记罪证 136、货被查封;镇压期间黑市页显示下线(改成实时读取游戏事件,原来要等过夜才更新)。
|
||||
- 没有在游戏里验证:平台跑路时订单和出售一起清零(单元测试覆盖)、死投点已删除。
|
||||
|
||||
### 第三阶段:数值调优(进行中)
|
||||
|
||||
- 混币器每轮手续费 6% → 4%;用币付款的顾客概率提到上层 30%、黑市 50%、革命派 50%、下层 25%,并多付 12%(溢价只加在币数上,污点仍按货值算)。
|
||||
- 区块奖励 90 → 100;RX800 耗电 12 → 14 kJ。
|
||||
- 减半对币价的传导改成每次在 0.15–0.85 的指数里随机(锚 +11% 到 +80%),历次累计存档。
|
||||
- 低档次的卡也会被冒充:新增废片芯片 RX10(不上架,只作假卡背后的真实芯片)。
|
||||
- 型号档次与实物不符(供电口、风扇数)的卡,摆给顾客时必被看穿并扣信誉(原来 50%),堵住用标签机把低档卡改成高档型号转卖的漏洞。
|
||||
- 显卡型号改名:Probidia RZX → RTX,PMD RZ → RX(RTX 60/70/80/90,RX 70/80/800/900);贴图重新生成。旧存档里的旧型号物品不再识别。
|
||||
- 散落的常量收进 `Tuning.cs`:买家看穿率与信誉封顶、杰克逊博士上货、二手贩子来访 / 种类 / 加价 / 假卡 / 隐瞒、显卡价值下限、非主交易对套利与深度。型号表、成色折价、外观阈值是数据表,仍留在原文件。
|
||||
- 单元测试 8909 项通过。游戏内验证:模组载入、型号改名后的卡名、币付款成交(4 件种子 118 信用点 → 132.16 CRT = ×1.12,污点按热度 50% 计 59)。成交后顾客那句话也看到了画面:原来的整句太长,被出售面板挡住,改成"成交,132 CRT。",累计一单的总数。没有在游戏里跑到:废片假卡、减半随机幅度(只有单元测试)。
|
||||
|
||||
### 第二阶段(进行中)
|
||||
|
||||
- 开发者模式 F9 新增 `Run night (test)`、`Morning report (test)`、`Newspaper (test)`(走游戏自己的夜间流程并进入下一天,事件按天数过期)和 `Start crackdown (test)`,用来测夜间逻辑;`Tainted wallet (test)` 现在同时给 1000 CRT。
|
||||
|
||||
- CRT 冻结:镇压事件开始时,按黑市声望(声望 0 时 40%,每点 −0.8%,50 以上不会)冻结钱包里一半的 CRT,3 天后解冻;冻结部分仍计入余额与估值,但不能交易、不能存混币器。Web3 页钱包下显示"CRT 冻结 N,第 X 天解冻";上报纸,夜间日志写冻结与解冻。开发者模式 F9 有 `Frozen CRT (test)`。游戏内验证了冻结显示、晨间日志里的冻结那行、超额卖出被拒、镇压事件触发冻结(黑市声望 0,多次镇压里命中一次)和 3 天后夜间解冻。税与稽查不做(游戏本身没有税)。
|
||||
|
||||
- 人脉网络里本 mod 单独一页"Web3":入口(400)和混币器(700,需先加入)都放在这页。
|
||||
- 混币器:终端 Web3 页里多一个"混币器"子页(买了升级才出现,和"交易"并列)。选币种、数量、1–5 轮,存入后每轮扣 6% 手续费并降低污点(基准每轮 35%,存入越大清洗越差,匿名集 = 2 万信用点背景量 + 存入量),轮数即等待天数,到期提回同一个地址;提回后一周内出金审查按"来自混币器"加重。镇压事件开始时 50% 被制裁 5 天,期间提出的币地址被标记,并上报纸;每晚 0.4% 跑路。夜间日志写提回与污点变化。开发者模式 F9 有 `Tainted wallet (test)`。游戏内验证了解锁、页面、存入与污点带走,夜间提回(50 PSC 存两轮,当时手续费 2%,提回 48.02,污点 1500 → 777,与预览一致)和镇压触发制裁,报纸上的制裁新闻。
|
||||
|
||||
- 用币付款的顾客:排队的买家里,上层付 CRC(12%)、黑市付 CRT(25%)、革命派付 CRA(25%)、下层付 PSC(10%)。成交时扣回信用点(现金不变),按当日币价换成币进热钱包,顾客当场说一句"成交,N CRT 已转入热钱包";赃物款项不记销赃,改成币带污点(货值 × 赃物热度%);夜间日志汇总当天用币结算的额度。开发者模式 F9 有测试入口(Coin buyer)。已在游戏里实测:成交后现金不变,四笔种子按币价记入 CRT,顾客对话显示。
|
||||
|
||||
### 第一阶段完成(入门、挖矿、显卡鉴定、终端)
|
||||
|
||||
以下条目取代下面较早条目里已过时的部分(型号、入口价、终端页面):
|
||||
|
||||
- 显卡改成每个牌子四档(低端、中端、高端、旗舰):Probidia RTX 60 / 70 / 80 / 90,PMD RX 70 / 80 / 800 / 900;型号只是显示名,性能由牌子和档次定;档次对应供电口(6 / 8 / 8 / 8+8 针)和风扇数(1 / 2 / 3 / 3)。显卡 3×2 格,正反面各一张图;价格约为最初的 1.8 倍,出块奖励 90。
|
||||
- 显卡外观:叶片、金手指、挡板、封条,随每晚损耗变差,影响价值、算力、损耗、暴毙。
|
||||
- 二手卡贩子(老实人、中间商、骗子)、假卡(低档芯片套高档壳)、序列号(牌子前缀、档次码、工厂码、流水)、背面丝印、鉴定公会收显卡、显卡鉴定手册。
|
||||
- 放大镜检视显卡:专门的大图和标签栏(型号真伪加叶片、金手指、挡板、封条四项成色),卖家说法与逐项指出、标签机改说法、买家验货与按价差扣信誉。
|
||||
- 减半抬高价格锚(传导 0.6,减半前一周有预期行情,减半前 3 天上报纸)。
|
||||
- 交易终端重做:首页三个入口(银行、Poinbase、Web3)加报告;左右分栏表格;买入均价;Web3 页的稳定币价格与状态;银行提取前的审查提示;金额输入框加宽。
|
||||
- 入口升级价 400,开局送交易终端、矿架、RTX 60 和鉴定手册。
|
||||
- 经济模拟 v7(运维库 research/sim/out_v7.md):电网电价下 RTX 70 挖矿第 30 天占总收入 18%、第 60 天 20%。
|
||||
|
||||
- 纯逻辑层:带种子的随机数、资产登记、地址账本(污点与成本随币走)、恒定乘积交易对、挖矿(显卡、矿机、全网算力、减半、损耗与暴毙)。
|
||||
- 纯逻辑层:市场(价格锚、情绪、游戏事件冲击、NPC 大户、多交易对套利回归、当日均价),三种稳定币(CRC 脱锚与减记、CRT 脱锚与冻结概率、CRA 补贴池与死亡螺旋),合规出金与 AML(大额与累计阈值、污点比例、轻度与重度命中、只对收益计税)。
|
||||
- mod 本体(第一阶段的第一部分):人脉网络"Web3 治理社区"(300,整个 mod 的入口)交付交易终端和一张 RZX 50;矿架向杰克逊博士购买;矿架是带电池槽和 4 个显卡槽的机器,每晚从电池扣电挖 PSC;显卡按型号显示算力、耗电与健康度,每晚损耗并可能烧毁;交易终端有钱包、交易(四个交易对、存入信用点、提取 CRC 过合规审查)、报告三页;夜间结算写晨间日志;PSC 交易所开业与减半上报纸;状态存进游戏的 mod 存档数据。中英双语。
|
||||
- mod 本体(第一阶段的第一部分):人脉网络"Web3 治理社区"(300,整个 mod 的入口)交付交易终端和一张 RTX 50;矿架向杰克逊博士购买;矿架是带电池槽和 4 个显卡槽的机器,每晚从电池扣电挖 PSC;显卡按型号显示算力、耗电与健康度,每晚损耗并可能烧毁;交易终端有钱包、交易(四个交易对、存入信用点、提取 CRC 过合规审查)、报告三页;夜间结算写晨间日志;PSC 交易所开业与减半上报纸;状态存进游戏的 mod 存档数据。中英双语。
|
||||
- 物品图:art/sprites.py 生成显卡(Probidia、PMD、烧毁)、矿架、交易终端。
|
||||
- 矿架加入游戏原有的通用模块槽:性能、效率、品质三项百分比折算 1/4 后作用于算力、耗电和显卡损耗,算力最多 +20%、省电最多 25%、损耗最多 −30%;性能加成同时提高损耗与暴毙率。取代原计划的 mod 自带超频模块。
|
||||
- 杰克逊博士上货(游戏给 mod 的进货钩子,夜间去他店里或他每周来本店摆摊时):没有矿架时必有一个,有了之后 30% 再上;基础显卡每次两张;进阶显卡第 10 天起 60%(再 30% 多一张);旗舰第 30 天起 25%,特供货事件时第 20 天起必有。全新真货,价格为物品价值加他的加价。加入 Web3 治理社区后才上货。开发者模式 F9 有测试入口。
|
||||
@@ -16,4 +399,4 @@
|
||||
- 矿架默认 2 个显卡槽,投入电子元件升级,最多 5 个:第 3 槽 4 个普通电子元件,第 4 槽 1 个稀有,第 5 槽 2 个稀有。窗口里新增"升级槽位",只收下一级需要的元件,放进去立即消耗并累计进度;显卡格子的形状随槽数变化,槽数与进度存在矿架标签上。
|
||||
|
||||
- 矿架的"基础耗电"标签随显卡变化(机身 + 各卡耗电,不含模块),游戏装卸模块时据此重算,不会把耗电改回只有机身的 2 kJ。
|
||||
- Web3 治理社区改为同时送一个矿架:交易终端、矿架、一张 RZX 50,送的货值 520;解锁价定为 400(见运维库定价说明)。
|
||||
- Web3 治理社区改为同时送一个矿架:交易终端、矿架、一张 RTX 50,送的货值 520;解锁价定为 400(见运维库定价说明)。
|
||||
@@ -0,0 +1,12 @@
|
||||
# 项目规则
|
||||
|
||||
## 数值
|
||||
|
||||
- 数值全部放在同一个配置类里(`src/Decentralized.Domain/Tuning.cs`,可以用嵌套类按主题划分),代码、测试里不写魔数。
|
||||
- 手册、说明文字里的数值不手写:用占位符 `{Name}`、`{Name:%}`、`{Name[2]:%}`(嵌套类用 `{Section.Name}`),由 `TuningText.Render` 在显示时从配置类取值。数值一改,文字跟着变。
|
||||
- 新增数值:先加进 `Tuning`,再登记到运营仓库的 `docs/tuning-index.md`,说明文字里用占位符引用。
|
||||
- 单元测试(`TuningText` 那一条)检查中英文手册的占位符都取得到值。
|
||||
|
||||
## 文案
|
||||
|
||||
- 界面标签用名词,提示用陈述句,不口语化;NPC 对话和报纸正文除外。界面不放说明文字,规则说明写进手册。
|
||||
@@ -1,6 +1,6 @@
|
||||
# Probably Decentralized
|
||||
|
||||
A mod for *Probably Stolen*: crypto mining, a fictional coin market, stablecoins, laundering and its risks, built on the game's own power, events and law systems. Work in progress; nothing is released yet.
|
||||
A mod for *Probably Stolen*: crypto mining, a fictional coin market, stablecoins, laundering and its risks, a Web3 black market, built on the game's own power, events and law systems. Current version: 1.1.0.
|
||||
|
||||
All coins, exchanges and events are fictional and have no real-world value.
|
||||
|
||||
@@ -8,10 +8,25 @@ All coins, exchanges and events are fictional and have no real-world value.
|
||||
|
||||
| Path | Content |
|
||||
|---|---|
|
||||
| `src/Decentralized.Domain` | Pure logic (assets and ledger, AMM pairs, market, mining). No game or Unity references. |
|
||||
| `src/Decentralized` | The mod: items (trading terminal, mining rig, graphics cards), nightly settlement, terminal window, news. Builds into `<game>/Mods/ProbablyDecentralized` (`dotnet build src/Decentralized -p:GameDir=...`). |
|
||||
| `src/Decentralized.Domain` | Pure logic (assets and ledger, AMM pairs, market, mining, graphics card tiers, appearance, labels and serials). No game or Unity references. |
|
||||
| `src/Decentralized` | The mod: items (trading terminal, mining rig, graphics cards, appraisal guide), used-card dealer, magnifier inspection view with the label bar, nightly settlement, terminal (bank, Poinbase, Web3 with trading, mining, mixer and the black market), black-market shelves, orders, courier and selling, Ponero desk, Web3 handbook, news. Builds into `<game>/Mods/ProbablyDecentralized` (`dotnet build src/Decentralized -p:GameDir=...`). |
|
||||
| `tests/Decentralized.Domain.Tests` | Console test runner: `dotnet run --project tests/Decentralized.Domain.Tests` |
|
||||
| `art/sprites.py` | Generates the item sprites into `src/Decentralized/ModFiles/Textures/Items`. |
|
||||
| `art/sprites.py`, `art/big.py`, `art/big_cases.py` | Generate the item sprites, the large inspection art and its overlays, and the terminal icons into `src/Decentralized/ModFiles/Textures/Items`. |
|
||||
|
||||
## Settings
|
||||
|
||||
Mod settings are in the game's mod list (select the mod, gear button); they apply to all saves.
|
||||
|
||||
| Section | Setting | Values |
|
||||
|---|---|---|
|
||||
| Interface | Trading terminal size | 828×680, 1200×900 (default), 1400×1000. Layout and text scale with the window; applies when the terminal is next opened. |
|
||||
| Story | Tumbler storyline | on / off. Off stops new visits; progress already made is kept. |
|
||||
| Difficulty | Risk multiplier | ×0.5 / ×1 / ×1.5 / ×2 on the chance of scams, rug pulls, wallet poisoning, address hijacking and phishing. |
|
||||
| Difficulty | Mining reward multiplier | ×0.5 / ×1 / ×1.5 / ×2 on the block reward paid to the player's rigs. |
|
||||
|
||||
## Languages
|
||||
|
||||
The interface follows the game language: en, zh, de, fr, es, pl, ru, ja. English is the source text; zh is hand-written; the other six are AI translations and have not been proofread. Tables are in `src/Decentralized/ModFiles/Localization/<code>.csv`.
|
||||
|
||||
## License
|
||||
|
||||
@@ -19,4 +34,4 @@ MIT, see `LICENSE`.
|
||||
|
||||
---
|
||||
|
||||
《Probably Stolen》的 mod:挖矿、虚构币市场、稳定币、洗钱及其风险,接入游戏原有的电力、事件和执法系统。开发中,尚未发布。所有币种、交易所和事件均为虚构,不具有任何现实价值。
|
||||
《Probably Stolen》的 mod:挖矿、虚构币市场、稳定币、洗钱及其风险、Web3 黑市,接入游戏原有的电力、事件和执法系统。开发中,尚未发布。所有币种、交易所和事件均为虚构,不具有任何现实价值。
|
||||
@@ -0,0 +1,443 @@
|
||||
#!/usr/bin/env python3
|
||||
"""显卡检视大图(192×128):放大镜检视台里用的细节图,不是小图的放大版。
|
||||
正面:七叶风扇、鳍片、热管、供电口、PCB 元件与逐根金手指;背面:拉丝背板、丝印凹槽、二维码与条码贴纸、封条。
|
||||
叠加图与底图同尺寸、坐标一致,只画变化的像素。"""
|
||||
import math
|
||||
import random
|
||||
from sprites import Canvas, C, key, MODELS
|
||||
|
||||
BW, BH = 192, 128
|
||||
# 风扇布局(按风扇数):中心与半径;FANS / FR 保留为双风扇的值,给叠加图模块当默认
|
||||
FAN_LAYOUT = {1: ([(105, 55)], 34), 2: ([(68, 51), (142, 51)], 30), 3: ([(52, 51), (96, 51), (140, 51)], 21)}
|
||||
FANS, FR = FAN_LAYOUT[2][0], FAN_LAYOUT[2][1]
|
||||
SH0, SH1 = (24, 14), (186, 96) # 散热罩 左上 / 右下
|
||||
FING_Y0, FING_Y1 = 109, 122
|
||||
NOTCH_X = 112
|
||||
|
||||
# 5×7 像素字(丝印与品牌字)
|
||||
F57 = {
|
||||
'R': ['11110', '10001', '10001', '11110', '10100', '10010', '10001'],
|
||||
'Z': ['11111', '00001', '00010', '00100', '01000', '10000', '11111'],
|
||||
'X': ['10001', '10001', '01010', '00100', '01010', '10001', '10001'],
|
||||
'P': ['11110', '10001', '10001', '11110', '10000', '10000', '10000'],
|
||||
'M': ['10001', '11011', '10101', '10101', '10001', '10001', '10001'],
|
||||
'D': ['11110', '10001', '10001', '10001', '10001', '10001', '11110'],
|
||||
'T': ['11111', '00100', '00100', '00100', '00100', '00100', '00100'],
|
||||
'i': ['00100', '00000', '01100', '00100', '00100', '00100', '01110'],
|
||||
'O': ['01110', '10001', '10001', '10001', '10001', '10001', '01110'],
|
||||
'B': ['11110', '10001', '10001', '11110', '10001', '10001', '11110'],
|
||||
'I': ['01110', '00100', '00100', '00100', '00100', '00100', '01110'],
|
||||
'A': ['01110', '10001', '10001', '11111', '10001', '10001', '10001'],
|
||||
'0': ['01110', '10001', '10011', '10101', '11001', '10001', '01110'],
|
||||
'1': ['00100', '01100', '00100', '00100', '00100', '00100', '01110'],
|
||||
'2': ['01110', '10001', '00001', '00110', '01000', '10000', '11111'],
|
||||
'3': ['11110', '00001', '00001', '01110', '00001', '00001', '11110'],
|
||||
'4': ['00010', '00110', '01010', '10010', '11111', '00010', '00010'],
|
||||
'5': ['11111', '10000', '11110', '00001', '00001', '10001', '01110'],
|
||||
'6': ['00110', '01000', '10000', '11110', '10001', '10001', '01110'],
|
||||
'7': ['11111', '00001', '00010', '00100', '01000', '01000', '01000'],
|
||||
'8': ['01110', '10001', '10001', '01110', '10001', '10001', '01110'],
|
||||
'9': ['01110', '10001', '10001', '01111', '00001', '00010', '01100'],
|
||||
}
|
||||
|
||||
|
||||
def text57(c, x, y, s, color, scale=1, skew=False, gap=1):
|
||||
i = 0
|
||||
for ch in s:
|
||||
if ch == ' ':
|
||||
x += 3 * scale
|
||||
continue
|
||||
dy = (i % 2) * scale if skew else 0
|
||||
for r, row in enumerate(F57[ch]):
|
||||
for k, bit in enumerate(row):
|
||||
if bit == '1':
|
||||
c.rect(x + k * scale, y + r * scale + dy, x + k * scale + scale - 1, y + r * scale + scale - 1 + dy, color)
|
||||
x += (5 + gap) * scale + (scale if skew and i % 3 == 2 else 0)
|
||||
i += 1
|
||||
|
||||
|
||||
def outline(c, col='O'):
|
||||
solid = lambda v: v is not None
|
||||
get = lambda x, y: c.px[y][x] if 0 <= x < c.w and 0 <= y < c.h else None
|
||||
edge = [(x, y) for y in range(c.h) for x in range(c.w)
|
||||
if solid(get(x, y)) and any(not solid(get(x + dx, y + dy)) for dx, dy in ((1, 0), (-1, 0), (0, 1), (0, -1)))]
|
||||
for x, y in edge:
|
||||
c.put(x, y, col)
|
||||
|
||||
|
||||
def bracket(c):
|
||||
"""左端 I/O 挡板:折边、三个接口(HDMI 与两个 DP,内腔与触片)、散热网孔、底部螺丝。"""
|
||||
c.rect(2, 8, 22, 112, 'b')
|
||||
c.rect(2, 8, 4, 112, 'l'); c.rect(2, 8, 2, 112, 'h') # 受光折边
|
||||
c.rect(19, 8, 22, 112, 'd'); c.rect(21, 8, 22, 112, 'g') # 背光折边
|
||||
for x in range(5, 19): # 拉丝
|
||||
for y in range(9, 112, 2):
|
||||
c.put(x, y, 'b' if (x + y) % 5 else 'l')
|
||||
for i, y in enumerate((16, 36, 56)): # 三个接口
|
||||
c.rect(6, y, 17, y + 13, 'k')
|
||||
c.rect(6, y, 17, y, 'g'); c.rect(6, y, 6, y + 13, 'g')
|
||||
c.rect(7, y + 1, 16, y + 12, 'n')
|
||||
if i == 0: # HDMI:两侧斜角
|
||||
for k in range(3):
|
||||
c.put(7 + k, y + 12 - k, 'k'); c.put(16 - k, y + 12 - k, 'k')
|
||||
c.rect(9, y + 4, 14, y + 6, 'z')
|
||||
else: # DP:一边切角
|
||||
c.put(16, y + 12, 'k'); c.put(15, y + 12, 'k'); c.put(16, y + 11, 'k')
|
||||
c.rect(9, y + 4, 14, y + 5, 'z')
|
||||
for x in range(8, 16, 2):
|
||||
c.put(x, y + 9, 'Y')
|
||||
for y in range(78, 104, 4): # 散热网孔
|
||||
for x in range(7, 17, 3):
|
||||
c.rect(x, y, x + 1, y + 2, 'k')
|
||||
c.put(x, y, 'x')
|
||||
c.rect(9, 106, 14, 110, 'm'); c.rect(10, 107, 13, 109, 'g') # 底部螺丝
|
||||
c.put(11, 108, 'k'); c.put(12, 108, 'k'); c.put(11, 107, 'b')
|
||||
c.rect(9, 10, 14, 12, 'k')
|
||||
|
||||
|
||||
def fan(c, cx, cy, accent, accent_dark, R=None):
|
||||
"""风扇:九片弯曲扇叶(前缘高光、叶面渐变、叶尖暗边),外圈带四个固定螺丝,轴心带品牌圆标。"""
|
||||
R = R or FR
|
||||
for y in range(cy - R - 1, cy + R + 2):
|
||||
for x in range(cx - R - 1, cx + R + 2):
|
||||
dx, dy = x - cx, y - cy
|
||||
r = math.hypot(dx, dy)
|
||||
if r > R + 0.5:
|
||||
continue
|
||||
ang = (math.atan2(dy, dx) / (2 * math.pi)) % 1.0
|
||||
light = -(dx + dy) / (1.4 * R) # 左上为正
|
||||
if r >= R - 3.2: # 外圈
|
||||
c.put(x, y, 'h' if light > 0.5 else 'l' if light > 0.1 else 'b' if light > -0.4 else 'm')
|
||||
elif r >= R - 5.5: # 风道阴影
|
||||
c.put(x, y, 'n' if light < 0.2 else 'k')
|
||||
elif r <= 6.5: # 轴心
|
||||
if r <= 4.3:
|
||||
c.put(x, y, accent if light < 0.3 else accent_dark if r > 3 else 'w')
|
||||
else:
|
||||
c.put(x, y, 'h' if light > 0.2 else 'm' if light > -0.3 else 'd')
|
||||
else:
|
||||
t = (ang * 9 + (r - 7) * 0.060) % 1.0
|
||||
if t < 0.62:
|
||||
if t < 0.06:
|
||||
col = 'h'
|
||||
elif t < 0.40:
|
||||
col = 'l' if light > 0.25 else 'b' if light > -0.2 else 'm'
|
||||
else:
|
||||
col = 'b' if light > 0.2 else 'm' if light > -0.3 else 'g'
|
||||
if r > R - 8:
|
||||
col = 'g' if col in ('m', 'g') else 'm'
|
||||
c.put(x, y, col)
|
||||
else:
|
||||
c.put(x, y, 'n' if t < 0.9 else 'k')
|
||||
for k in range(4): # 外圈固定螺丝
|
||||
a = math.pi / 4 + k * math.pi / 2
|
||||
sx, sy = int(cx + math.cos(a) * (R - 1.5)), int(cy + math.sin(a) * (R - 1.5))
|
||||
c.rect(sx - 1, sy - 1, sx + 1, sy + 1, 'k')
|
||||
c.put(sx, sy, 'g')
|
||||
|
||||
|
||||
def gpu_front(accent, accent_dark, brand_text, tier=1, burnt=False, count=None, pin=None):
|
||||
"""tier 决定实物特征:风扇数(1/2/3/3)与供电口(6 针 / 8 针 / 8 针 / 双 8 针)。"""
|
||||
count = count or (1, 2, 3, 3)[tier]
|
||||
pin = (0, 1, 1, 2)[tier] if pin is None else pin
|
||||
fans, R = FAN_LAYOUT[count]
|
||||
c = Canvas(BW, BH)
|
||||
bracket(c)
|
||||
x0, y0 = SH0
|
||||
x1, y1 = SH1
|
||||
# 散热罩:石墨底,顶部受光亮边,左缘高光,右下阴影;右上角切斜
|
||||
for y in range(y0, y1 + 1):
|
||||
for x in range(x0, x1 + 1):
|
||||
if x > x1 - 8 and y < y0 + (x - (x1 - 8)): # 右上切角
|
||||
continue
|
||||
base = 'z'
|
||||
if y < y0 + 3: base = 'h' if x < x1 - 40 else 'l'
|
||||
elif y < y0 + 6: base = 'l' if x < x1 - 40 else 'b'
|
||||
elif y < y0 + 9: base = 'x'
|
||||
elif y > y1 - 4: base = 'n'
|
||||
c.put(x, y, base)
|
||||
for y in range(y0 + 3, y1): # 左缘
|
||||
c.put(x0, y, 'l'); c.put(x0 + 1, y, 'b'); c.put(x0 + 2, y, 'x')
|
||||
# 右端鳍片
|
||||
for x in range(x1 - 18, x1 + 1):
|
||||
for y in range(y0 + 10, y1 - 4):
|
||||
if x > x1 - 8 and y < y0 + (x - (x1 - 8)) + 2:
|
||||
continue
|
||||
c.put(x, y, 'x' if (x - (x1 - 18)) % 3 == 0 else 'g' if (x - (x1 - 18)) % 3 == 1 else 'n')
|
||||
c.rect(x1 - 20, y0 + 10, x1 - 19, y1 - 4, 'x')
|
||||
# 风扇之间的中筋
|
||||
for a, b in zip(fans, fans[1:]):
|
||||
mx = (a[0] + b[0]) // 2 + 1
|
||||
c.rect(mx - 1, y0 + 8, mx, y1 - 5, 'k'); c.rect(mx + 1, y0 + 8, mx + 1, y1 - 5, 'x')
|
||||
for cx, cy in fans:
|
||||
fan(c, cx, cy, accent, accent_dark, R)
|
||||
# 前沿斜切装饰条:品牌色 + 品牌字
|
||||
for x in range(x0 + 4, x1 - 20):
|
||||
c.rect(x, y1 - 5, x, y1 - 3, accent if x % 11 else accent_dark)
|
||||
text57(c, 30 if count == 1 else 112, 84, brand_text, 'h') # 单风扇的大风扇占了右边,品牌字改放左下
|
||||
# 顶沿:四根铜热管端头与 8 针供电口
|
||||
for i in range(4):
|
||||
x = 38 + i * 9
|
||||
c.rect(x, 7, x + 6, y0 - 1, 'p'); c.rect(x, 7, x + 1, y0 - 1, 'h' if i == 0 else 'p')
|
||||
c.rect(x + 5, 7, x + 6, y0 - 1, 'q'); c.rect(x, 7, x + 6, 7, 'q')
|
||||
# 供电口:低端 6 针;中端、高端 8 针;旗舰两个 8 针
|
||||
for left, pins in ((((118, 6),) if pin == 0 else ((112, 8),) if pin == 1 else ((78, 8), (126, 8)))):
|
||||
right = left + pins * 5 + 2
|
||||
c.rect(left, 5, right, y0 - 1, 'n'); c.rect(left, 5, right, 6, 'z')
|
||||
for i in range(pins):
|
||||
c.rect(left + 2 + i * 5, 7, left + 4 + i * 5, 9, 'k'); c.put(left + 3 + i * 5, 8, 'Y')
|
||||
# PCB:阻焊绿、边缘高光、元件与走线
|
||||
for y in range(y1 + 1, FING_Y0):
|
||||
for x in range(x0, x1 + 1):
|
||||
c.put(x, y, 'G' if y < y1 + 4 else 'g2')
|
||||
for x in range(x0, x1 + 1):
|
||||
c.put(x, y1 + 1, 'T') if False else None
|
||||
random.seed(7)
|
||||
for i in range(14):
|
||||
sx = x0 + 6 + i * 11
|
||||
c.rect(sx, y1 + 3, sx + 3, y1 + 5, 'k' if i % 3 else 'b')
|
||||
c.rect(sx, y1 + 3, sx + 3, y1 + 3, 'x')
|
||||
for k in range(4):
|
||||
c.put(sx + k, y1 + 7, 'Y' if k % 2 == 0 else 'g2')
|
||||
# 金手指:逐根(3 像素宽,1 像素缝),PCIe 键位缺口
|
||||
for x in range(x0 + 2, x1 - 2):
|
||||
if NOTCH_X - 2 <= x <= NOTCH_X + 3 or (x - x0) % 4 == 3:
|
||||
continue
|
||||
for y in range(FING_Y0, FING_Y1 + 1):
|
||||
c.put(x, y, 'h' if y == FING_Y0 else 'Y' if (x - x0) % 4 != 0 else 'p')
|
||||
c.put(x, FING_Y1, 'e')
|
||||
c.rect(x0, FING_Y0, x1, FING_Y0, 'g2')
|
||||
for y in range(FING_Y0 + 1, FING_Y1 + 1): # 缝里露出 PCB
|
||||
for x in range(x0 + 2, x1 - 2):
|
||||
if c.px[y][x] is None and not (NOTCH_X - 2 <= x <= NOTCH_X + 3):
|
||||
c.put(x, y, 'g2')
|
||||
if burnt:
|
||||
for cx, cy in FANS:
|
||||
for dx, dy in ((0, 0), (5, -5), (-6, 6), (8, 4), (-9, -3), (2, 10)):
|
||||
c.rect(cx + dx - 2, cy + dy - 2, cx + dx + 2, cy + dy + 2, 'c')
|
||||
for x in range(x0 + 4, x1 - 20):
|
||||
c.rect(x, y1 - 5, x, y1 - 3, 'e')
|
||||
for dx, dy in ((30, 70), (90, 40), (150, 80), (60, 30), (120, 88)):
|
||||
c.rect(dx, dy, dx + 4, dy + 3, 'c')
|
||||
outline(c)
|
||||
return c
|
||||
|
||||
|
||||
def screw(c, x, y):
|
||||
c.rect(x - 3, y - 3, x + 3, y + 3, 'm')
|
||||
c.rect(x - 3, y - 3, x - 1, y - 3, 'h')
|
||||
c.rect(x - 2, y - 2, x + 2, y + 2, 'b')
|
||||
c.rect(x - 2, y, x + 2, y, 'k'); c.rect(x, y - 2, x, y + 2, 'k')
|
||||
c.rect(x + 2, y + 2, x + 3, y + 3, 'd')
|
||||
|
||||
|
||||
def qr(c, x, y, seed):
|
||||
rnd = random.Random(seed)
|
||||
n = 21
|
||||
c.rect(x - 1, y - 1, x + n, y + n, 'w')
|
||||
for j in range(n):
|
||||
for i in range(n):
|
||||
on = rnd.random() < 0.5
|
||||
for fx, fy in ((0, 0), (n - 7, 0), (0, n - 7)):
|
||||
if fx <= i < fx + 7 and fy <= j < fy + 7:
|
||||
li, lj = i - fx, j - fy
|
||||
on = li in (0, 6) or lj in (0, 6) or (2 <= li <= 4 and 2 <= lj <= 4)
|
||||
elif fx - 1 <= i <= fx + 7 and fy - 1 <= j <= fy + 7:
|
||||
on = False
|
||||
if on:
|
||||
c.put(x + i, y + j, 'n')
|
||||
|
||||
|
||||
def sticker(c, seed):
|
||||
"""序列号贴纸(右下):二维码、条码、两行小字。"""
|
||||
c.rect(86, 64, 172, 100, 'w')
|
||||
c.rect(86, 64, 172, 65, 'h'); c.rect(86, 99, 172, 100, 'l')
|
||||
c.rect(86, 64, 87, 100, 'h'); c.rect(171, 64, 172, 100, 'l')
|
||||
qr(c, 91, 70, seed)
|
||||
for x in range(118, 166):
|
||||
w = 1 + ((x * 7 + seed) % 3)
|
||||
if (x * 5 + seed) % 4 != 0:
|
||||
c.rect(x, 70, x, 84, 'n')
|
||||
|
||||
|
||||
def seal(c):
|
||||
"""封条(红底白字):压住贴纸右边缘。"""
|
||||
c.rect(174, 60, 182, 104, 'R')
|
||||
c.rect(174, 60, 175, 104, 'r2'); c.rect(181, 60, 182, 104, 'r2')
|
||||
for y in range(66, 100, 8):
|
||||
c.rect(176, y, 180, y + 3, 'w')
|
||||
c.put(178, y + 1, 'R')
|
||||
|
||||
|
||||
def gpu_back(accent, accent_dark, burnt=False):
|
||||
c = Canvas(BW, BH)
|
||||
bracket(c)
|
||||
x0, y0 = SH0
|
||||
x1, y1 = SH1
|
||||
for y in range(y0, y1 + 12):
|
||||
for x in range(x0, x1 + 1):
|
||||
c.put(x, y, 'd' if y % 2 else 'm' if (x // 3) % 4 else 'd')
|
||||
for y in range(y0, y1 + 12):
|
||||
c.put(x0, y, 'l'); c.put(x0 + 1, y, 'b'); c.put(x1, y, 'k'); c.put(x1 - 1, y, 'z')
|
||||
for x in range(x0, x1 + 1):
|
||||
c.put(x, y0, 'h'); c.put(x, y0 + 1, 'l'); c.put(x, y0 + 2, 'b')
|
||||
# 丝印凹槽(型号叠加图写在这里)
|
||||
c.rect(36, 24, 178, 52, 'z')
|
||||
c.rect(36, 24, 178, 25, 'k'); c.rect(36, 24, 37, 52, 'k')
|
||||
c.rect(36, 52, 178, 52, 'x'); c.rect(178, 24, 178, 52, 'x')
|
||||
# 品牌色斜条
|
||||
for x in range(x0 + 4, x1 - 4):
|
||||
c.rect(x, 56, x, 59, accent)
|
||||
c.put(x, 60, accent_dark)
|
||||
# 通风槽(左下)
|
||||
for y in range(70, 100, 6):
|
||||
c.rect(x0 + 10, y, x0 + 50, y + 3, 'k')
|
||||
c.rect(x0 + 10, y + 4, x0 + 50, y + 4, 'x')
|
||||
# 四角螺丝
|
||||
for sx, sy in ((x0 + 12, y0 + 10), (x1 - 12, y0 + 10), (x0 + 12, y1 - 2), (x1 - 12, y1 - 2)):
|
||||
screw(c, sx, sy)
|
||||
sticker(c, 5)
|
||||
seal(c)
|
||||
# 背面金手指(暗一档):触点之间是 PCB 的深绿,只有键位缺口是空的
|
||||
for y in range(y1 + 12, FING_Y1 + 1):
|
||||
for x in range(x0, x1 + 1):
|
||||
if NOTCH_X - 2 <= x <= NOTCH_X + 3 and y > y1 + 13:
|
||||
continue
|
||||
c.put(x, y, 'g2')
|
||||
for x in range(x0 + 2, x1 - 2):
|
||||
if NOTCH_X - 2 <= x <= NOTCH_X + 3 or (x - x0) % 4 == 3:
|
||||
continue
|
||||
for y in range(y1 + 14, FING_Y1 + 1):
|
||||
c.put(x, y, 'Y' if (x - x0) % 4 else 'p')
|
||||
if burnt:
|
||||
for dx, dy in ((60, 30), (130, 40), (50, 80), (100, 70), (150, 90)):
|
||||
c.rect(dx, dy, dx + 6, dy + 4, 'c')
|
||||
outline(c)
|
||||
return c
|
||||
|
||||
|
||||
def new():
|
||||
return Canvas(BW, BH)
|
||||
|
||||
|
||||
# ---------- 叠加图 ----------
|
||||
|
||||
def ov_fan(kind):
|
||||
c = new()
|
||||
rnd = random.Random(11 + kind)
|
||||
for cx, cy in FANS:
|
||||
if kind == 1: # 积灰:叶片上一层灰点和灰絮
|
||||
for _ in range(190):
|
||||
a = rnd.random() * math.tau
|
||||
r = 8 + rnd.random() * (FR - 12)
|
||||
x, y = int(cx + math.cos(a) * r), int(cy + math.sin(a) * r)
|
||||
c.put(x, y, 'l' if rnd.random() < 0.6 else 'h')
|
||||
if rnd.random() < 0.3:
|
||||
c.put(x + 1, y, 'l')
|
||||
for _ in range(10): # 絮状长条
|
||||
a = rnd.random() * math.tau
|
||||
r = 10 + rnd.random() * (FR - 16)
|
||||
x, y = int(cx + math.cos(a) * r), int(cy + math.sin(a) * r)
|
||||
for k in range(5):
|
||||
c.put(x + k, y + (k // 2), 'w' if k % 2 == 0 else 'l')
|
||||
else: # 缺角:一片叶尖缺一块,露出风道黑底
|
||||
a0 = 0.9 if cx < 100 else 3.2
|
||||
for r in range(10, FR - 3):
|
||||
for da in (-0.20, -0.17, -0.13, -0.10, -0.06, -0.02, 0.02, 0.06, 0.10, 0.14):
|
||||
if r > FR - 14 + (da * 30) and r > 17:
|
||||
c.put(int(cx + math.cos(a0 + da) * r), int(cy + math.sin(a0 + da) * r), 'n')
|
||||
for r in range(17, FR - 3):
|
||||
c.put(int(cx + math.cos(a0 - 0.22) * r), int(cy + math.sin(a0 - 0.22) * r), 'h')
|
||||
return c
|
||||
|
||||
|
||||
def ov_fingers(kind):
|
||||
c = new()
|
||||
rnd = random.Random(21 + kind)
|
||||
x0, x1 = SH0[0], SH1[0]
|
||||
for x in range(x0 + 2, x1 - 2):
|
||||
if NOTCH_X - 2 <= x <= NOTCH_X + 3 or (x - x0) % 4 == 3:
|
||||
continue
|
||||
for y in range(FING_Y0 + 1, FING_Y1 + 1):
|
||||
if kind == 1: # 发暗:触点变褐
|
||||
c.put(x, y, 'e' if (x + y) % 3 else 'q')
|
||||
else: # 氧化:发绿的斑块
|
||||
if rnd.random() < 0.65:
|
||||
c.put(x, y, 'g2' if rnd.random() < 0.5 else 'G')
|
||||
return c
|
||||
|
||||
|
||||
def ov_bracket(kind):
|
||||
c = new()
|
||||
rnd = random.Random(31)
|
||||
if kind == 1: # 划痕
|
||||
for _ in range(9):
|
||||
x, y = rnd.randint(5, 17), rnd.randint(14, 100)
|
||||
for k in range(rnd.randint(5, 12)):
|
||||
c.put(x + k // 2, y + k, 'h' if k % 2 else 'k')
|
||||
else: # 接口数不对:第三个接口被板子封死
|
||||
c.rect(6, 56, 17, 69, 'b')
|
||||
c.rect(6, 56, 17, 56, 'h'); c.rect(6, 56, 6, 69, 'l'); c.rect(17, 56, 17, 69, 'd')
|
||||
for x in range(7, 17, 2):
|
||||
c.put(x, 62, 'm')
|
||||
return c
|
||||
|
||||
|
||||
def ov_text(model, skew):
|
||||
c = new()
|
||||
text57(c, 46, 31, model, 'l' if skew else 'h', scale=2, skew=skew, gap=1)
|
||||
return c
|
||||
|
||||
|
||||
def ov_sticker(kind):
|
||||
c = new()
|
||||
if kind == 1: # 手写序列号
|
||||
c.rect(86, 64, 172, 100, 'w')
|
||||
c.rect(86, 64, 172, 65, 'h'); c.rect(86, 99, 172, 100, 'l')
|
||||
c.rect(86, 64, 87, 100, 'h'); c.rect(171, 64, 172, 100, 'l')
|
||||
rnd = random.Random(41)
|
||||
for row in (74, 84, 92):
|
||||
x = 92
|
||||
while x < 164:
|
||||
w = rnd.randint(3, 7)
|
||||
for k in range(w):
|
||||
c.put(x + k, row + int(math.sin(k + x) * 1.5), 'O')
|
||||
c.put(x + k, row + 1 + int(math.sin(k + x) * 1.5), 'O')
|
||||
x += w + rnd.randint(2, 4)
|
||||
else: # 封条缺失:残留的胶痕与撕口
|
||||
c.rect(174, 60, 182, 104, 'd')
|
||||
for y in range(60, 105, 3):
|
||||
c.rect(174, y, 178 + (y % 5), y + 1, 'm')
|
||||
for y in range(62, 104, 6):
|
||||
c.rect(179, y, 181, y + 1, 'x')
|
||||
return c
|
||||
|
||||
|
||||
BIG = {}
|
||||
for _b, (_a, _ad, _t) in {'probidia': ('G', 'g2', 'PROBIDIA'), 'pmd': ('R', 'r2', 'PMD')}.items():
|
||||
for _tier in range(4):
|
||||
BIG['gpu_big_%s_f_t%d' % (_b, _tier)] = (lambda a=_a, ad=_ad, t=_t, k=_tier: gpu_front(a, ad, t, k))
|
||||
for _pin in range(3): # 供电口与风扇数各自独立(假卡可以只对不上其中一项)
|
||||
for _n in range(1, 4):
|
||||
BIG['gpu_big_%s_f_p%dn%d' % (_b, _pin, _n)] = (lambda a=_a, ad=_ad, t=_t, p=_pin, n=_n: gpu_front(a, ad, t, 1, count=n, pin=p))
|
||||
BIG['gpu_big_%s_b' % _b] = (lambda a=_a, ad=_ad: gpu_back(a, ad))
|
||||
BIG['gpu_big_burnt_f'] = lambda: gpu_front('e', 'c', 'PROBIDIA', 1, burnt=True)
|
||||
BIG['gpu_big_burnt_b'] = lambda: gpu_back('e', 'c', burnt=True)
|
||||
BIG_OV = {}
|
||||
|
||||
if __name__ == '__main__':
|
||||
import sys, os
|
||||
if len(sys.argv) == 3 and sys.argv[1] == '--preview':
|
||||
d = sys.argv[2]
|
||||
def stack(base, *ovs):
|
||||
b = BIG[base]()
|
||||
for o in ovs:
|
||||
oc = BIG_OV[o]()
|
||||
for y in range(oc.h):
|
||||
for x in range(oc.w):
|
||||
if oc.px[y][x] is not None:
|
||||
b.px[y][x] = oc.px[y][x]
|
||||
return b
|
||||
bg = (0x6A, 0x72, 0x70)
|
||||
for t in range(4):
|
||||
stack('gpu_big_probidia_f_t%d' % t).png(os.path.join(d, 'big_f_t%d.png' % t), scale=3, bg=bg)
|
||||
@@ -30,6 +30,20 @@ C = {
|
||||
'Y': (0xC8, 0xA4, 0x4A), # 金手指
|
||||
'c': (0x2E, 0x2A, 0x2A), # 焦黑
|
||||
'e': (0x6B, 0x4A, 0x3A), # 焦痕
|
||||
'u': (0x4F, 0x86, 0xD0), # 蓝
|
||||
'U': (0x2B, 0x4A, 0x82), # 深蓝
|
||||
'v': (0x9B, 0x76, 0xD6), # 紫
|
||||
'V': (0x5E, 0x45, 0x8F), # 深紫
|
||||
'y': (0xF0, 0xCF, 0x64), # 亮金
|
||||
'p': (0xC0, 0x7A, 0x4A), # 铜
|
||||
'q': (0x8A, 0x4F, 0x34), # 暗铜
|
||||
'w': (0xE6, 0xE2, 0xD0), # 白
|
||||
'n': (0x1E, 0x1B, 0x25), # 近黑
|
||||
'x': (0x4A, 0x4E, 0x58), # 石墨亮边
|
||||
'z': (0x2D, 0x2F, 0x38), # 石墨暗
|
||||
'P': (0xD8, 0xDA, 0xD0), # 墨水屏
|
||||
'K': (0x3C, 0x3F, 0x48), # 石墨机身
|
||||
'E': (0x5A, 0x5E, 0x6A), # 机身受光边
|
||||
}
|
||||
|
||||
|
||||
@@ -77,86 +91,308 @@ class Canvas:
|
||||
f.write(data)
|
||||
|
||||
|
||||
def gpu(accent, accent_dark, burnt=False):
|
||||
"""显卡(32×32,2×2 格),略微俯视:顶面是带两个风扇的散热罩,左端金属挡板(带接口),
|
||||
前沿露出 PCB 和金手指,右端一道暗侧面,顶上一排供电口。每格中心都不透明。"""
|
||||
c = Canvas(32, 32)
|
||||
TOP0, TOP1 = 4, 22 # 顶面行范围
|
||||
L, R = 6, 29 # 顶面左右(左边是挡板)
|
||||
# 金属 I/O 挡板(左端竖条,带两个接口孔)
|
||||
c.rect(1, 2, 5, 27, 'b')
|
||||
c.rect(1, 2, 1, 27, 'h'); c.rect(5, 2, 5, 27, 'd')
|
||||
for y in (6, 12): # 两个视频接口(深色矩形孔,带高光边)
|
||||
c.rect(2, y, 4, y + 3, 'k')
|
||||
c.rect(2, y, 4, y, 'g')
|
||||
c.put(3, 20, 'k'); c.put(3, 22, 'k'); c.put(3, 24, 'k') # 下部散热孔
|
||||
# 散热罩顶面
|
||||
for y in range(TOP0, TOP1 + 1):
|
||||
for x in range(L, R + 1):
|
||||
c.put(x, y, 'm')
|
||||
c.put(R, y, 'd'); c.put(R - 1, y, 'd')
|
||||
for x in range(L, R + 1):
|
||||
c.put(x, TOP0, 'l'); c.put(x, TOP0 + 1, 'b')
|
||||
# 品牌色条(沿罩顶前沿)
|
||||
for x in range(L + 1, R - 1):
|
||||
c.put(x, TOP1 - 1, accent)
|
||||
c.put(L + 1, TOP1, accent_dark); c.put(R - 2, TOP1, accent_dark)
|
||||
# 两个风扇(圆形,叶片用十字 + 斜线)
|
||||
for cx in (11, 22):
|
||||
cy = 13
|
||||
for y in range(cy - 6, cy + 7):
|
||||
for x in range(cx - 6, cx + 7):
|
||||
d2 = (x - cx) ** 2 + (y - cy) ** 2
|
||||
if d2 <= 36:
|
||||
c.put(x, y, 'k')
|
||||
if 20 <= d2 <= 30:
|
||||
c.put(x, y, 'g')
|
||||
for k in range(-4, 5):
|
||||
if abs(k) >= 1:
|
||||
c.put(cx + k, cy, 'g'); c.put(cx, cy + k, 'g')
|
||||
c.put(cx - 2, cy - 2, 'g'); c.put(cx + 2, cy + 2, 'g'); c.put(cx + 2, cy - 2, 'g'); c.put(cx - 2, cy + 2, 'g')
|
||||
c.rect(cx - 1, cy - 1, cx + 1, cy + 1, 'b')
|
||||
c.put(cx, cy, 'h')
|
||||
# 前沿:PCB 绿色薄边 + 金手指
|
||||
for x in range(L, R + 1):
|
||||
c.put(x, TOP1 + 1, 'g2')
|
||||
c.put(x, TOP1 + 2, 'g2')
|
||||
for x in range(L, R + 1): # 金手指:连续金色带,中间一道缺口(PCIe 键位),带深色触点线
|
||||
c.put(x, TOP1 + 3, 'Y'); c.put(x, TOP1 + 4, 'Y' if x % 2 == 0 else 'e')
|
||||
for y in (TOP1 + 3, TOP1 + 4):
|
||||
c.put(L + 13, y, 'k'); c.put(L + 14, y, 'k')
|
||||
# 顶上一排供电口(两个黑色插口)
|
||||
for x0 in (L + 3, L + 9):
|
||||
c.rect(x0, TOP0 - 1, x0 + 4, TOP0 - 1, 'k')
|
||||
# 保证每格中心不透明:下半部(第二行格子,y 16..31 的中心 y=24)落在金手指/PCB 上
|
||||
for x in range(L, R + 1):
|
||||
for y in range(TOP1 + 1, 28):
|
||||
if c.px[y][x] is None:
|
||||
c.put(x, y, 'k')
|
||||
if burnt:
|
||||
for x, y in [(9, 8), (10, 9), (13, 17), (24, 8), (25, 9), (27, 18), (17, 12), (18, 11)]:
|
||||
c.put(x, y, 'c')
|
||||
for x in range(L + 1, R - 1):
|
||||
c.put(x, TOP1 - 1, 'e')
|
||||
for x, y in [(15, 5), (16, 5), (20, 21), (26, 14)]:
|
||||
c.put(x, y, 'c')
|
||||
# 轮廓
|
||||
FONT = { # 3×5 像素字(丝印用)
|
||||
'R': '110101110101101', 'Z': '111001010100111', 'X': '101101010101101', 'P': '110101110100100',
|
||||
'M': '101111111101101', 'D': '110101101101110', 'T': '111010010010010', 'i': '010000010010010',
|
||||
'0': '111101101101111', '1': '010110010010111', '2': '110001010100111', '3': '110001010001110',
|
||||
'4': '101101111001001', '5': '111100110001110', '6': '011100111101111', '7': '111001010010010',
|
||||
'8': '111101111101111', '9': '111101111001110',
|
||||
}
|
||||
|
||||
|
||||
def text(c, x, y, s, color, skew=False):
|
||||
"""在画布上写 3×5 像素字;skew 为重新印过的效果:字一高一低、间距不匀。"""
|
||||
i = 0
|
||||
for ch in s:
|
||||
if ch == ' ':
|
||||
x += 2
|
||||
continue
|
||||
dy = (i % 2) if skew else 0
|
||||
for k, bit in enumerate(FONT[ch]):
|
||||
if bit == '1':
|
||||
c.put(x + k % 3, y + k // 3 + dy, color)
|
||||
x += 4 + (1 if skew and i % 3 == 2 else 0)
|
||||
i += 1
|
||||
|
||||
|
||||
W, H = 48, 32
|
||||
TOP0, TOP1 = 4, 22 # 顶面行范围
|
||||
L, R = 6, 45 # 顶面左右(左边是挡板)
|
||||
FANS = ((17, 13), (34, 13)) # 两个风扇中心
|
||||
|
||||
|
||||
def outline(c):
|
||||
solid = lambda v: v is not None
|
||||
get = lambda x, y: c.px[y][x] if 0 <= x < c.w and 0 <= y < c.h else None
|
||||
edge = [(x, y) for y in range(c.h) for x in range(c.w)
|
||||
if solid(get(x, y)) and any(not solid(get(x + dx, y + dy)) for dx, dy in ((1, 0), (-1, 0), (0, 1), (0, -1)))]
|
||||
for x, y in edge:
|
||||
c.put(x, y, 'O')
|
||||
|
||||
|
||||
def bracket(c):
|
||||
"""左端金属挡板:带折边、网孔、三个接口(带高光边与内壁)、底部固定螺丝。"""
|
||||
c.rect(1, 2, 5, 27, 'b')
|
||||
c.rect(1, 2, 1, 27, 'h'); c.rect(2, 2, 2, 27, 'l'); c.rect(5, 2, 5, 27, 'd'); c.rect(4, 2, 4, 27, 'm')
|
||||
for y in (5, 11, 17): # 三个接口:外框亮边、内腔深色、中间一条触片
|
||||
c.rect(2, y, 4, y + 3, 'k')
|
||||
c.rect(2, y, 4, y, 'h'); c.put(2, y + 1, 'g'); c.put(4, y + 1, 'g')
|
||||
c.put(3, y + 2, 'd'); c.put(3, y + 3, 'g')
|
||||
for y in range(20, 27, 2): # 散热网孔
|
||||
c.put(2, y, 'k'); c.put(4, y, 'k')
|
||||
c.put(3, y + 1, 'k')
|
||||
c.put(3, 3, 'k'); c.put(3, 27, 'g') # 顶部卡扣与底部螺丝
|
||||
c.put(2, 27, 'h'); c.put(4, 27, 'd')
|
||||
|
||||
|
||||
def fan(c, cx, cy, accent, burnt=False, R=7):
|
||||
"""风扇:深色风道里六片弯曲扇叶(前缘高光、叶面按受光渐变),外圈细边,轴心带品牌色点;光从左上来。"""
|
||||
import math
|
||||
k = 7.0 / R # 按半径折算到 R=7 的画法
|
||||
for y in range(cy - R, cy + R + 1):
|
||||
for x in range(cx - R, cx + R + 1):
|
||||
dx, dy = x - cx, y - cy
|
||||
r = math.hypot(dx, dy) * k
|
||||
if r > 7.4:
|
||||
continue
|
||||
ang = (math.atan2(dy, dx) / (2 * math.pi)) % 1.0
|
||||
lit = (dx + dy) < 0
|
||||
if r >= 6.5: # 外圈细边
|
||||
c.put(x, y, 'l' if dx + dy < -3 else ('b' if dx + dy < 3 else 'g'))
|
||||
elif r >= 5.6: # 风道
|
||||
c.put(x, y, 'n')
|
||||
elif r <= 2.3: # 轴心
|
||||
c.put(x, y, 'h' if (dx + dy) < -1 else 'b' if dx + dy < 2 else 'm')
|
||||
else:
|
||||
t = (ang * 6 + (r - 3) * 0.16) % 1.0
|
||||
if t < 0.55:
|
||||
c.put(x, y, 'h' if t < 0.09 else ('l' if lit else 'b') if t < 0.30 else ('b' if lit else 'm'))
|
||||
else:
|
||||
c.put(x, y, 'n' if t < 0.85 else 'k')
|
||||
c.put(cx, cy, accent)
|
||||
c.put(cx - 1, cy - 1, 'w')
|
||||
|
||||
|
||||
FAN_LAYOUT_SMALL = {1: ([(26, 13)], 9), 2: ([(17, 13), (34, 13)], 7), 3: ([(14, 13), (26, 13), (38, 13)], 5)}
|
||||
|
||||
|
||||
def gpu_front(accent, accent_dark, burnt=False, tier=1, count=None, pin=None):
|
||||
"""显卡正面(48×32,3×2 格),略微俯视:石墨色散热罩带斜切角与品牌色斜条,两个七叶风扇,
|
||||
右端露出鳍片,顶沿露出铜热管和 8 针供电口,前沿是带元件的 PCB 和逐根画出的金手指。每格中心都不透明。"""
|
||||
c = Canvas(W, H)
|
||||
bracket(c)
|
||||
# 散热罩底色:左上亮、右下暗的渐变,右上角切角
|
||||
for y in range(TOP0, TOP1 + 1):
|
||||
for x in range(L, R + 1):
|
||||
c.put(x, y, 'x' if y < TOP0 + 3 else 'd' if (x - L) < 4 else 'z')
|
||||
for x in range(L, R + 1):
|
||||
c.put(x, TOP0, 'h' if x < R - 5 else 'l'); c.put(x, TOP0 + 1, 'l' if x < R - 8 else 'b')
|
||||
for y in range(TOP0, TOP1 + 1): # 左缘受光
|
||||
c.put(L, y, 'l'); c.put(L + 1, y, 'b')
|
||||
# 右端鳍片(竖向细条)
|
||||
for x in range(R - 4, R + 1):
|
||||
for y in range(TOP0 + 2, TOP1):
|
||||
c.put(x, y, 'g' if (x - (R - 4)) % 2 == 0 else 'k')
|
||||
c.rect(R - 5, TOP0 + 2, R - 5, TOP1 - 1, 'x')
|
||||
count = count or (1, 2, 3, 3)[tier]
|
||||
pin = (0, 1, 1, 2)[tier] if pin is None else pin
|
||||
fans, fr = FAN_LAYOUT_SMALL[count]
|
||||
# 风扇之间的筋条
|
||||
for a, b in zip(fans, fans[1:]):
|
||||
mx = (a[0] + b[0]) // 2
|
||||
for y in range(TOP0 + 3, TOP1 - 2):
|
||||
c.put(mx, y, 'k'); c.put(mx + 1, y, 'x')
|
||||
# 品牌色斜条(从前沿向左上延伸)与前沿色条
|
||||
for x in range(L + 1, R - 5):
|
||||
c.put(x, TOP1 - 1, accent if x % 9 else accent_dark)
|
||||
c.put(x, TOP1, accent_dark)
|
||||
for cx, cy in fans:
|
||||
fan(c, cx, cy, accent, R=fr)
|
||||
if count < 3:
|
||||
for dx, dy in ((-7, -7), (7, -7), (-7, 7), (7, 7)): # 风扇四角的固定孔
|
||||
c.put(cx + dx, cy + dy, 'n' if dx + dy else 'k')
|
||||
# 顶沿:铜热管端头 + 8 针供电口(带针脚)
|
||||
for x0 in (L + 6, L + 8, L + 10, L + 12):
|
||||
c.put(x0, TOP0 - 1, 'p'); c.put(x0 + 1, TOP0 - 1, 'q')
|
||||
# 供电口:低端 6 针;中端、高端 8 针;旗舰两个 8 针(每针占两像素)
|
||||
for left, pins in (((L + 22, 6),) if pin == 0 else ((L + 18, 8),) if pin == 1 else ((L + 8, 8), (L + 25, 8))):
|
||||
for x in range(left, left + pins * 2):
|
||||
c.put(x, TOP0 - 1, 'n')
|
||||
for x in range(left, left + pins * 2, 2):
|
||||
c.put(x, TOP0 - 2, 'k')
|
||||
for x in range(left + 1, left + pins * 2, 2):
|
||||
c.put(x, TOP0 - 2, 'Y')
|
||||
# 前沿:PCB(绿)带元件,之后金手指
|
||||
for x in range(L, R + 1):
|
||||
c.put(x, TOP1 + 1, 'G' if x % 7 else 'g2'); c.put(x, TOP1 + 2, 'g2')
|
||||
for x0 in (L + 4, L + 11, L + 22, L + 29):
|
||||
c.put(x0, TOP1 + 1, 'b'); c.put(x0 + 1, TOP1 + 1, 'g')
|
||||
for x in range(L, R + 1): # 金手指:每一根带深色分隔
|
||||
if x in (L + 17, L + 18):
|
||||
continue
|
||||
c.put(x, TOP1 + 3, 'Y' if x % 2 == 0 else 'e'); c.put(x, TOP1 + 4, 'Y' if x % 2 == 0 else 'q')
|
||||
c.put(x, TOP1 + 5, 'e' if x % 2 == 0 else 'k')
|
||||
for x in range(L, R + 1):
|
||||
for y in range(TOP1 + 1, 28):
|
||||
if c.px[y][x] is None:
|
||||
c.put(x, y, 'k')
|
||||
if burnt:
|
||||
for x, y in [(12, 8), (13, 9), (18, 17), (35, 8), (36, 9), (40, 18), (24, 12), (25, 11), (19, 9), (33, 16)]:
|
||||
c.put(x, y, 'c')
|
||||
for x in range(L + 1, R - 5):
|
||||
c.put(x, TOP1 - 1, 'e')
|
||||
for cx, cy in fans:
|
||||
for dx, dy in ((0, 0), (1, 1), (-1, 1), (2, -2), (-2, -2)):
|
||||
c.put(cx + dx, cy + dy, 'c')
|
||||
outline(c)
|
||||
return c
|
||||
|
||||
|
||||
def screw(c, x, y):
|
||||
c.put(x, y, 'b'); c.put(x + 1, y, 'g'); c.put(x, y + 1, 'g'); c.put(x + 1, y + 1, 'k')
|
||||
|
||||
|
||||
def gpu_back(accent, accent_dark, burnt=False):
|
||||
"""显卡背面(翻面后):左端仍是挡板;拉丝金属背板,带通风槽、四角螺丝、品牌色斜条;
|
||||
中上是一块凹进去的丝印区(型号用叠加图写在这里),右下是带二维码和条码的序列号贴纸,贴纸边上一道封条。"""
|
||||
c = Canvas(W, H)
|
||||
bracket(c)
|
||||
for y in range(TOP0, 28):
|
||||
for x in range(L, R + 1):
|
||||
c.put(x, y, 'd' if (y % 3) else 'm' if x % 2 else 'd')
|
||||
c.put(R, y, 'k'); c.put(R - 1, y, 'z')
|
||||
for x in range(L, R + 1):
|
||||
c.put(x, TOP0, 'l'); c.put(x, TOP0 + 1, 'b')
|
||||
for y in range(TOP0, 28):
|
||||
c.put(L, y, 'b'); c.put(L + 1, y, 'x')
|
||||
# 丝印凹槽
|
||||
c.rect(9, 7, 43, 13, 'z')
|
||||
c.rect(9, 7, 43, 7, 'k'); c.rect(9, 7, 9, 13, 'k')
|
||||
c.rect(9, 13, 43, 13, 'x')
|
||||
# 品牌色斜条与前沿色条
|
||||
for x in range(L + 1, R - 1):
|
||||
c.put(x, 16, accent)
|
||||
c.put(L + 1, 17, accent_dark); c.put(R - 2, 17, accent_dark)
|
||||
# 通风槽(左下一组)
|
||||
for y in (19, 21, 23, 25):
|
||||
for x in range(L + 4, L + 14):
|
||||
c.put(x, y, 'k')
|
||||
for x in range(L + 4, L + 14):
|
||||
c.put(x, y + 1, 'x') if y + 1 < 27 else None
|
||||
# 四角螺丝
|
||||
for x, y in ((L + 2, TOP0 + 3), (R - 5, TOP0 + 3), (L + 2, 24), (R - 5, 24)):
|
||||
screw(c, x, y)
|
||||
# 序列号贴纸:左边二维码,右边条码与小字
|
||||
c.rect(22, 17, 41, 23, 'w')
|
||||
c.rect(22, 17, 41, 17, 'h'); c.rect(22, 23, 41, 23, 'l')
|
||||
qr = ['1110101', '1010011', '1011101', '0001010', '1101111', '0100101', '1110011']
|
||||
for j, row in enumerate(qr):
|
||||
for i, ch in enumerate(row):
|
||||
if ch == '1':
|
||||
c.put(23 + i, 17 + j - (1 if j == 6 else 0) * 0, 'n') if j < 6 else None
|
||||
for x in range(31, 41, 2):
|
||||
c.rect(x, 18, x, 20, 'n')
|
||||
for x in range(32, 41, 3):
|
||||
c.put(x, 18, 'w'); c.put(x, 19, 'w')
|
||||
for x in range(31, 41):
|
||||
if x % 3 != 0:
|
||||
c.put(x, 22, 'm')
|
||||
# 封条(红底白字)
|
||||
c.rect(43, 16, 44, 24, 'R')
|
||||
c.rect(43, 16, 43, 24, 'r2')
|
||||
for y in (18, 20, 22):
|
||||
c.put(44, y, 'w')
|
||||
# 背面金手指一行
|
||||
for x in range(L, R + 1):
|
||||
if x in (L + 17, L + 18):
|
||||
continue
|
||||
c.put(x, 27, 'Y' if x % 2 == 0 else 'e')
|
||||
if burnt:
|
||||
for x, y in [(14, 9), (15, 10), (30, 11), (36, 13), (20, 14), (26, 21), (12, 22)]:
|
||||
c.put(x, y, 'c')
|
||||
outline(c)
|
||||
return c
|
||||
|
||||
|
||||
def overlay():
|
||||
return Canvas(W, H)
|
||||
|
||||
|
||||
def ov_fan(kind, count=2):
|
||||
"""风扇叠加:1 积灰(叶片上一层灰),2 叶片缺角(边缘缺一块并露出黑底)。"""
|
||||
c = overlay()
|
||||
for cx, cy in FAN_LAYOUT_SMALL[count][0]:
|
||||
if kind == 1:
|
||||
for dx, dy in ((-4, -2), (-2, -4), (3, -3), (4, 1), (-3, 3), (2, 4), (-5, 0), (0, 5), (1, -5), (-1, 2), (5, -1), (3, 2)):
|
||||
c.put(cx + dx, cy + dy, 'l')
|
||||
for dx, dy in ((-4, -1), (-1, -4), (4, -2), (2, 3), (-3, 4)):
|
||||
c.put(cx + dx, cy + dy, 'h')
|
||||
else:
|
||||
for dx, dy in ((4, -4), (5, -4), (5, -3), (4, -3), (3, -4), (5, -5), (6, -3)):
|
||||
c.put(cx + dx, cy + dy, 'k')
|
||||
c.put(cx - 5, cy + 4, 'k'); c.put(cx - 4, cy + 5, 'k'); c.put(cx - 5, cy + 5, 'k')
|
||||
return c
|
||||
|
||||
|
||||
def ov_fingers(kind):
|
||||
"""金手指叠加:1 发暗(触点变褐),2 氧化发绿。"""
|
||||
c = overlay()
|
||||
for x in range(L, R + 1):
|
||||
for y in (TOP1 + 3, TOP1 + 4):
|
||||
if x in (L + 17, L + 18):
|
||||
continue
|
||||
if kind == 1:
|
||||
c.put(x, y, 'e' if (x + y) % 3 else 'Y')
|
||||
else:
|
||||
c.put(x, y, 'g2' if (x + y) % 2 else 'G')
|
||||
return c
|
||||
|
||||
|
||||
def ov_bracket(kind):
|
||||
"""挡板叠加:1 划痕;2 接口数量不对(第三个接口被封成一块平板,只剩两个)。"""
|
||||
c = overlay()
|
||||
if kind == 1:
|
||||
for x, y in ((2, 9), (3, 10), (4, 11), (2, 15), (3, 15), (3, 16), (2, 20), (3, 21), (4, 22), (4, 25), (3, 25)):
|
||||
c.put(x, y, 'l' if (x + y) % 2 else 'd')
|
||||
else:
|
||||
c.rect(2, 17, 4, 20, 'b')
|
||||
c.rect(2, 17, 4, 17, 'h')
|
||||
return c
|
||||
|
||||
|
||||
def ov_text(model, skew):
|
||||
"""背面丝印叠加:写型号。skew 为重新印过的版本(字高低不齐)。"""
|
||||
c = overlay()
|
||||
text(c, 10, 8, model, 'l' if skew else 'h', skew)
|
||||
return c
|
||||
|
||||
|
||||
def ov_sticker(kind):
|
||||
"""贴纸叠加:1 手写序列号(条码被盖住、写了歪歪扭扭的字);2 封条缺失(只剩撕过的残胶)。"""
|
||||
c = overlay()
|
||||
if kind == 1:
|
||||
c.rect(22, 17, 41, 23, 'w')
|
||||
c.rect(22, 17, 41, 17, 'h'); c.rect(22, 23, 41, 23, 'l')
|
||||
for x, y in ((24, 20), (25, 19), (26, 20), (27, 19), (29, 20), (30, 19), (30, 21), (32, 19), (33, 20), (34, 19), (35, 21), (36, 20), (37, 19), (38, 20), (39, 21), (24, 22), (26, 21), (28, 22), (31, 22), (35, 22)):
|
||||
c.put(x, y, 'O')
|
||||
else:
|
||||
c.rect(43, 16, 44, 24, 'd')
|
||||
for y in (16, 18, 20, 22, 24):
|
||||
c.put(44, y, 'm')
|
||||
c.put(43, 17, 'm'); c.put(43, 21, 'm'); c.put(43, 23, 'x')
|
||||
return c
|
||||
|
||||
|
||||
MODELS = ['RTX 60', 'RTX 70', 'RTX 80', 'RTX 90', 'RX 70', 'RX 80', 'RX 800', 'RX 900']
|
||||
|
||||
|
||||
def rig():
|
||||
"""矿架(48×48,3×3 格):和游戏里其他机器一样的略微俯视(3/4 视角)——顶面是上窄下宽的梯形,
|
||||
"""矿架(64×64,4×4 格):和游戏里其他机器一样的略微俯视(3/4 视角)——顶面是上窄下宽的梯形,
|
||||
下面是正面,正面里四层显卡位,左下角电源;光从左上来,左亮右暗;轮廓统一深紫、削掉尖角、底下两只脚和一圈阴影。"""
|
||||
c = Canvas(48, 48)
|
||||
FL, FR, FY, DEP = 3, 44, 24, 19 # 正面左右边、顶面前沿所在行、顶面深度(顶面后沿在 y=6,中心行 y=8 落在顶面上)
|
||||
BOT = 44 # 正面底边
|
||||
inset = lambda v: v // 6 # 顶面后部只略微收窄:原版机器的顶面也近似矩形,并且要让左右两格的中心落在顶面内
|
||||
c = Canvas(64, 64)
|
||||
FL, FR, FY, DEP = 3, 60, 36, 31 # 正面左右边、顶面前沿所在行、顶面深度(顶面后沿在 y=6,中心行 y=8 落在顶面上)
|
||||
BOT = 60 # 正面底边
|
||||
inset = lambda v: v // 8 # 顶面后部只略微收窄:原版机器的顶面也近似矩形,并且要让左右两格的中心落在顶面内
|
||||
|
||||
# 顶面:后部受光、前部稍暗;左缘亮、右缘暗
|
||||
for v in range(DEP):
|
||||
@@ -169,8 +405,8 @@ def rig():
|
||||
for x in range(FL + inset(DEP - 1), FR - inset(DEP - 1) + 1):
|
||||
c.put(x, FY - DEP + 1, 'l')
|
||||
# 顶面上的散热格栅和一个小指示灯
|
||||
for v in range(4, 16, 3):
|
||||
for u in range(6, 24):
|
||||
for v in range(4, 26, 3):
|
||||
for u in range(6, 34):
|
||||
c.put(FL + inset(v) + u, FY - v, 'g')
|
||||
c.put(FR - 9, FY - 8, 'G'); c.put(FR - 8, FY - 8, 'G')
|
||||
# 正面:中间色,左端受光、右端暗;顶部一条暗折线
|
||||
@@ -190,7 +426,7 @@ def rig():
|
||||
c.put(x, BOT - 1, 'd')
|
||||
# 正面里的四层显卡位(深色槽,上沿亮、下沿暗,右端一颗状态灯)
|
||||
# 正面四层显卡位(深色槽,右端一颗状态灯);间隔行用中间色,保证每格中心都不透明
|
||||
for i, y in enumerate((FY + 3, FY + 8, FY + 13)):
|
||||
for i, y in enumerate((FY + 3, FY + 8, FY + 13, FY + 18)):
|
||||
for x in range(FL + 3, FR - 4):
|
||||
for dy in range(3):
|
||||
c.put(x, y + dy, 'k')
|
||||
@@ -283,13 +519,274 @@ def terminal():
|
||||
return c
|
||||
|
||||
|
||||
def key(model):
|
||||
return model.replace(' ', '').lower()
|
||||
|
||||
|
||||
def ui_bank():
|
||||
"""银行图标(32×32):带山花的石柱建筑,门前一枚金币。"""
|
||||
c = Canvas(32, 32)
|
||||
for k in range(0, 14): # 山花(三角)
|
||||
c.rect(16 - k, 4 + k // 2, 16 + k, 4 + k // 2, 'h' if k < 3 else 'l')
|
||||
c.rect(2, 11, 29, 12, 'b'); c.rect(2, 13, 29, 13, 'd') # 檐口
|
||||
for x0 in (4, 10, 16, 22): # 四根柱子
|
||||
c.rect(x0, 14, x0 + 3, 24, 'l')
|
||||
c.rect(x0, 14, x0, 24, 'h'); c.rect(x0 + 3, 14, x0 + 3, 24, 'd')
|
||||
c.rect(x0 - 1, 14, x0 + 4, 14, 'b'); c.rect(x0 - 1, 24, x0 + 4, 24, 'b')
|
||||
c.rect(1, 25, 30, 26, 'b'); c.rect(0, 27, 31, 28, 'm'); c.rect(0, 29, 31, 29, 'd')
|
||||
c.rect(14, 8, 17, 9, 'y'); c.put(15, 8, 'w') # 山花里的小徽标
|
||||
for yy in range(19, 27): # 金币
|
||||
for xx in range(23, 31):
|
||||
d = (xx - 26.5) ** 2 + (yy - 22.5) ** 2
|
||||
if d <= 14:
|
||||
c.put(xx, yy, 'e' if d > 9 else 'y')
|
||||
c.put(25, 21, 'w'); c.put(26, 21, 'w'); c.put(26, 22, 'y')
|
||||
outline(c)
|
||||
return c
|
||||
|
||||
|
||||
def ui_poinbase():
|
||||
"""Poinbase 图标(32×32):蓝色盾牌,中间一枚金色 P 币,两侧一上一下的箭头。"""
|
||||
c = Canvas(32, 32)
|
||||
for y in range(3, 29): # 盾牌
|
||||
half = 12 if y < 16 else max(0, 12 - (y - 16) * 12 // 12)
|
||||
for x in range(16 - half, 16 + half + 1):
|
||||
c.put(x, y, 'u' if x < 16 else 'U')
|
||||
c.put(16 - half, y, 'h') if half else None
|
||||
for x in range(4, 29):
|
||||
c.put(x, 3, 'h'); c.put(x, 4, 'l')
|
||||
for y in range(7, 21): # 币
|
||||
for x in range(9, 24):
|
||||
d = (x - 16) ** 2 + (y - 13.5) ** 2
|
||||
if d <= 36:
|
||||
c.put(x, y, 'e' if d > 28 else 'y')
|
||||
c.put(12, 9, 'w'); c.put(13, 8, 'w'); c.put(12, 10, 'w')
|
||||
c.rect(13, 9, 14, 18, 'U'); c.rect(15, 9, 18, 10, 'U'); c.rect(18, 11, 19, 13, 'U'); c.rect(15, 14, 18, 15, 'U') # P
|
||||
for k in range(4): # 下方两个箭头:买入、卖出
|
||||
c.put(9 + k, 24 - k, 'w') if k < 3 else None
|
||||
for x in range(8, 13): c.put(x, 22, 'w')
|
||||
for x in range(19, 24): c.put(x, 22, 'w')
|
||||
c.put(19, 23, 'w'); c.put(20, 24, 'w'); c.put(23, 23, 'w'); c.put(22, 24, 'w')
|
||||
outline(c)
|
||||
return c
|
||||
|
||||
|
||||
def ui_web3():
|
||||
"""Web3 图标(32×32):六边形节点网络,紫色底。"""
|
||||
c = Canvas(32, 32)
|
||||
nodes = [(16, 7), (7, 14), (25, 14), (11, 24), (21, 24), (16, 16)]
|
||||
edges = [(0, 1), (0, 2), (1, 3), (2, 4), (3, 4), (5, 0), (5, 1), (5, 2), (5, 3), (5, 4)]
|
||||
for (a, b) in edges:
|
||||
(x0, y0), (x1, y1) = nodes[a], nodes[b]
|
||||
n = max(abs(x1 - x0), abs(y1 - y0))
|
||||
for i in range(n + 1):
|
||||
px, py = x0 + (x1 - x0) * i // n, y0 + (y1 - y0) * i // n
|
||||
c.put(px, py, 'v'); c.put(px + 1, py, 'v'); c.put(px, py + 1, 'v')
|
||||
for i, (x, y) in enumerate(nodes):
|
||||
r = 3 if i == 5 else 2
|
||||
for dy in range(-r, r + 1):
|
||||
for dx in range(-r, r + 1):
|
||||
if dx * dx + dy * dy <= r * r + 1:
|
||||
c.put(x + dx, y + dy, 'V' if (dx + dy) > 0 else 'h' if i != 5 else 'y')
|
||||
c.put(x, y, 'w')
|
||||
outline(c)
|
||||
return c
|
||||
|
||||
|
||||
def guide():
|
||||
"""鉴定手册(16×16,一格):竖放的小册子,封面带品牌色条,书脊在左。"""
|
||||
c = Canvas(16, 16)
|
||||
c.box(2, 1, 13, 14, 'b')
|
||||
c.rect(3, 2, 4, 13, 'd') # 书脊
|
||||
c.rect(5, 2, 12, 2, 'h')
|
||||
c.rect(6, 4, 11, 5, 'G') # 封面色块
|
||||
c.rect(6, 4, 11, 4, 'g2')
|
||||
for y in (7, 9, 11): # 文字行
|
||||
c.rect(6, y, 11 if y != 11 else 9, y, 'm')
|
||||
c.put(12, 13, 'd')
|
||||
outline(c)
|
||||
return c
|
||||
|
||||
|
||||
def asic(model):
|
||||
"""RatDigg 矿机(48×32,3×2 格):宽扁的金属机箱,正面两个大风扇,顶上一条铭牌带三个指示灯和型号;
|
||||
指示灯与风扇轴心的颜色区分档次(M1 绿、M2 蓝、M3 金)。光从左上来。"""
|
||||
c = Canvas(48, 32)
|
||||
accent = {'M1': 'G', 'M2': 'u', 'M3': 'y'}[model]
|
||||
c.rect(3, 1, 44, 5, 'l') # 顶面
|
||||
c.rect(3, 1, 44, 1, 'h')
|
||||
c.rect(43, 2, 44, 5, 'b')
|
||||
c.rect(2, 6, 45, 29, 'm') # 正面
|
||||
c.rect(2, 6, 2, 29, 'b'); c.rect(45, 6, 45, 29, 'd'); c.rect(2, 29, 45, 29, 'd')
|
||||
c.rect(4, 7, 43, 10, 'n') # 铭牌带
|
||||
for x in (6, 9, 12):
|
||||
c.put(x, 8, accent); c.put(x, 9, accent if x == 6 else 'k')
|
||||
text(c, 32, 7, model.replace('M', 'M'), 'w')
|
||||
for fx in (14, 34): # 风扇:方框风道 + 圆扇
|
||||
c.rect(fx - 9, 12, fx + 9, 28, 'n')
|
||||
c.rect(fx - 9, 12, fx + 9, 12, 'g'); c.rect(fx - 9, 12, fx - 9, 28, 'g')
|
||||
fan(c, fx, 20, accent, R=8)
|
||||
c.rect(22, 12, 26, 28, 'd') # 两扇之间的散热栅
|
||||
for y in range(13, 28, 2):
|
||||
c.rect(23, y, 25, y, 'k')
|
||||
c.rect(4, 30, 9, 31, 'k'); c.rect(38, 30, 43, 31, 'k') # 脚垫
|
||||
c.rect(10, 30, 37, 30, 'd')
|
||||
outline(c)
|
||||
return c
|
||||
|
||||
|
||||
def hw_wallet():
|
||||
"""PLEDGER 硬件钱包(16×16,一格):竖放的石墨卡片,大块浅色墨水屏,右侧一个侧键。"""
|
||||
c = Canvas(16, 16)
|
||||
c.rect(3, 1, 12, 14, 'K')
|
||||
for (x, y) in ((3, 1), (12, 1), (3, 14), (12, 14)):
|
||||
c.put(x, y, None)
|
||||
c.rect(4, 2, 4, 13, 'E'); c.rect(4, 2, 11, 2, 'E') # 左上受光
|
||||
c.rect(11, 3, 11, 13, 'z'); c.rect(5, 13, 11, 13, 'z') # 右下背光
|
||||
c.rect(5, 3, 10, 11, 'P') # 墨水屏
|
||||
c.rect(6, 5, 9, 5, 'm'); c.rect(6, 7, 8, 7, 'm'); c.rect(6, 9, 9, 9, 'm') # 屏上的字
|
||||
c.rect(13, 5, 13, 7, 'x') # 侧键
|
||||
outline(c)
|
||||
return c
|
||||
|
||||
|
||||
def key_drive():
|
||||
"""Tumbler 的密钥盘(16×16,一格):斜放的旧式数据棒,深紫机身、金属接口、一枚红色指示灯和手写标签。"""
|
||||
c = Canvas(16, 16)
|
||||
c.rect(3, 4, 12, 11, 'V') # 机身
|
||||
c.rect(3, 4, 12, 4, 'v'); c.rect(3, 4, 3, 11, 'v') # 受光边
|
||||
c.rect(4, 11, 12, 11, 'n'); c.rect(12, 5, 12, 11, 'n') # 背光边
|
||||
c.rect(13, 6, 15, 9, 'l'); c.rect(13, 9, 15, 9, 'm') # 金属接口
|
||||
c.put(14, 7, 'k'); c.put(14, 8, 'k')
|
||||
c.rect(5, 6, 9, 9, 'w') # 手写标签
|
||||
c.rect(6, 7, 8, 7, 'k'); c.rect(6, 8, 7, 8, 'k')
|
||||
c.put(11, 6, 'R') # 指示灯
|
||||
outline(c)
|
||||
return c
|
||||
|
||||
|
||||
SPRITES = {
|
||||
'gpu_probidia': lambda: gpu('G', 'g2'),
|
||||
'gpu_pmd': lambda: gpu('R', 'r2'),
|
||||
'gpu_burnt': lambda: gpu('e', 'c', burnt=True),
|
||||
'gpu_guide': guide,
|
||||
'gpu_burnt_f': lambda: gpu_front('e', 'c', burnt=True),
|
||||
'gpu_burnt_b': lambda: gpu_back('e', 'c', burnt=True),
|
||||
'gpu_probidia_b': lambda: gpu_back('G', 'g2'),
|
||||
'gpu_pmd_b': lambda: gpu_back('R', 'r2'),
|
||||
'rig': rig,
|
||||
'terminal': terminal,
|
||||
'hw_wallet': hw_wallet,
|
||||
'key_drive': key_drive,
|
||||
'asic_m1': lambda: asic('M1'),
|
||||
'asic_m2': lambda: asic('M2'),
|
||||
'asic_m3': lambda: asic('M3'),
|
||||
}
|
||||
for _tier in range(4):
|
||||
SPRITES['gpu_probidia_f_t%d' % _tier] = (lambda t=_tier: gpu_front('G', 'g2', tier=t))
|
||||
SPRITES['gpu_pmd_f_t%d' % _tier] = (lambda t=_tier: gpu_front('R', 'r2', tier=t))
|
||||
for _pin in range(3):
|
||||
for _n in range(1, 4):
|
||||
SPRITES['gpu_probidia_f_p%dn%d' % (_pin, _n)] = (lambda p=_pin, n=_n: gpu_front('G', 'g2', pin=p, count=n))
|
||||
SPRITES['gpu_pmd_f_p%dn%d' % (_pin, _n)] = (lambda p=_pin, n=_n: gpu_front('R', 'r2', pin=p, count=n))
|
||||
|
||||
def hw_button(symbol):
|
||||
"""硬件钱包的物理按键(24×24):石墨外圈、左上受光的金属环,中间凹下去的按键面,刻着 ✓ 或 ✕。"""
|
||||
c = Canvas(24, 24)
|
||||
for y in range(24):
|
||||
for x in range(24):
|
||||
d = ((x - 11.5) ** 2 + (y - 11.5) ** 2) ** 0.5
|
||||
if d <= 11.5:
|
||||
c.put(x, y, 'x' if x + y < 23 else 'z') # 外圈:左上亮、右下暗
|
||||
if d <= 9.5:
|
||||
c.put(x, y, 'k' if x + y < 23 else 'n') # 凹槽:反过来,左上暗、右下亮一点
|
||||
if d <= 8.5:
|
||||
c.put(x, y, 'z') # 按键面
|
||||
mark = 'G' if symbol == 'ok' else 'R'
|
||||
if symbol == 'ok':
|
||||
pts = [(7, 12), (8, 13), (9, 14), (10, 15), (11, 14), (12, 13), (13, 12), (14, 11), (15, 10), (16, 9)]
|
||||
else:
|
||||
pts = [(8 + k, 8 + k) for k in range(8)] + [(15 - k, 8 + k) for k in range(8)]
|
||||
for (x, y) in pts:
|
||||
c.put(x, y, mark); c.put(x, y + 1, mark)
|
||||
outline(c)
|
||||
return c
|
||||
|
||||
|
||||
def rounded(size, r, fill, light=None, dark=None):
|
||||
"""圆角矩形(九宫格用):圆角半径 r,外轮廓 O;可选左上一圈受光、右下一圈背光。"""
|
||||
c = Canvas(size, size)
|
||||
def inside(x, y, rr):
|
||||
cx = min(max(x, rr), size - 1 - rr); cy = min(max(y, rr), size - 1 - rr)
|
||||
return (x - cx) ** 2 + (y - cy) ** 2 <= rr * rr + rr * 0.6
|
||||
for y in range(size):
|
||||
for x in range(size):
|
||||
if inside(x, y, r):
|
||||
c.put(x, y, fill)
|
||||
if light or dark:
|
||||
for y in range(size):
|
||||
for x in range(size):
|
||||
if c.px[y][x] is None:
|
||||
continue
|
||||
edge = any(not (0 <= x + dx < size and 0 <= y + dy < size) or c.px[y + dy][x + dx] is None for dx, dy in ((2, 0), (-2, 0), (0, 2), (0, -2)))
|
||||
if edge:
|
||||
c.put(x, y, light if x + y < size - 1 else dark)
|
||||
outline(c)
|
||||
return c
|
||||
|
||||
|
||||
def hw_selected():
|
||||
"""PLEDGER 屏上选中的按钮(16×16,九宫格边 5):墨水屏白底、1 像素黑框,四角向外加粗的取景框角标(准星)。"""
|
||||
c = Canvas(16, 16)
|
||||
c.rect(0, 0, 15, 15, 'P')
|
||||
for i in range(16):
|
||||
c.put(i, 1, 'n'); c.put(i, 14, 'n'); c.put(1, i, 'n'); c.put(14, i, 'n')
|
||||
for (x, y, dx, dy) in ((0, 0, 1, 1), (15, 0, -1, 1), (0, 15, 1, -1), (15, 15, -1, -1)):
|
||||
for k in range(4):
|
||||
c.put(x + dx * k, y, 'n'); c.put(x, y + dy * k, 'n')
|
||||
return c
|
||||
|
||||
|
||||
def hw_groove():
|
||||
"""PLEDGER 墨水屏输入框凹槽(12×12,九宫格边 2):浅色底、1 像素深墨边。"""
|
||||
c = Canvas(12, 12)
|
||||
c.rect(0, 0, 11, 11, 'n')
|
||||
c.rect(1, 1, 10, 10, 'P')
|
||||
return c
|
||||
|
||||
|
||||
UI_ICONS = {'ui_bank': ui_bank, 'ui_poinbase': ui_poinbase, 'ui_web3': ui_web3}
|
||||
UI_ICONS['ui_hw_shell'] = lambda: rounded(32, 7, 'K', 'E', 'z')
|
||||
UI_ICONS['ui_hw_bezel'] = lambda: rounded(16, 4, 'n')
|
||||
UI_ICONS['ui_hw_paper'] = lambda: rounded(12, 2, 'P')
|
||||
UI_ICONS['ui_hw_sel'] = hw_selected
|
||||
def hw_key():
|
||||
"""触控键底图(九宫格,白色,可着色):圆角 3 像素,没有描边,颜色由界面按状态着色。"""
|
||||
size, r = 12, 3
|
||||
c = Canvas(size, size)
|
||||
for y in range(size):
|
||||
for x in range(size):
|
||||
cx = min(max(x, r), size - 1 - r); cy = min(max(y, r), size - 1 - r)
|
||||
if (x - cx) ** 2 + (y - cy) ** 2 <= r * r + r * 0.6:
|
||||
c.put(x, y, 'w')
|
||||
return c
|
||||
|
||||
|
||||
UI_ICONS['ui_hw_key'] = hw_key
|
||||
UI_ICONS['ui_hw_groove'] = hw_groove
|
||||
UI_ICONS['ui_hw_ok'] = lambda: hw_button('ok')
|
||||
UI_ICONS['ui_hw_no'] = lambda: hw_button('no')
|
||||
|
||||
# 叠加图:和底图同尺寸,位置 (0,0) 对齐,只画变化的像素,不参与判格
|
||||
OVERLAYS = {
|
||||
'gpu_ov_fin1': lambda: ov_fingers(1), 'gpu_ov_fin2': lambda: ov_fingers(2),
|
||||
'gpu_ov_brk1': lambda: ov_bracket(1),
|
||||
'gpu_ov_stk2': lambda: ov_sticker(2),
|
||||
}
|
||||
for _n in (1, 2, 3):
|
||||
OVERLAYS['gpu_ov_fan1_%d' % _n] = (lambda n=_n: ov_fan(1, n))
|
||||
OVERLAYS['gpu_ov_fan2_%d' % _n] = (lambda n=_n: ov_fan(2, n))
|
||||
for _m in MODELS:
|
||||
OVERLAYS['gpu_ov_txt_' + key(_m)] = (lambda m=_m: ov_text(m, False))
|
||||
OVERLAYS['gpu_ov_txs_' + key(_m)] = (lambda m=_m: ov_text(m, True))
|
||||
|
||||
|
||||
def check_cells(canvas, name):
|
||||
"""游戏按 mod 物品图每格的中心像素是否不透明来判断占格(行从图的下沿往上数)。有空格就报错。"""
|
||||
@@ -306,11 +803,48 @@ if __name__ == '__main__':
|
||||
canvas = make()
|
||||
check_cells(canvas, name)
|
||||
canvas.png(os.path.join(sys.argv[2], name + '.png'), scale=6, bg=(0xA0, 0xA8, 0x9C))
|
||||
# 预览:把各种叠加图叠在底图上
|
||||
def stack(base, *ovs):
|
||||
b = SPRITES[base]()
|
||||
for o in ovs:
|
||||
oc = OVERLAYS[o]()
|
||||
for y in range(oc.h):
|
||||
for x in range(oc.w):
|
||||
if oc.px[y][x] is not None:
|
||||
b.px[y][x] = oc.px[y][x]
|
||||
return b
|
||||
for name, make in UI_ICONS.items():
|
||||
make().png(os.path.join(sys.argv[2], name + '.png'), scale=8, bg=(0x2a, 0x2c, 0x34))
|
||||
stack('gpu_probidia_f_t1', 'gpu_ov_fan2_2', 'gpu_ov_fin1', 'gpu_ov_brk1').png(os.path.join(sys.argv[2], 'prev_front_worn.png'), scale=6, bg=(0xA0, 0xA8, 0x9C))
|
||||
print(sys.argv[2])
|
||||
else:
|
||||
out = os.path.normpath(os.path.join(here, '..', 'src', 'Decentralized', 'ModFiles', 'Textures', 'Items'))
|
||||
for f in os.listdir(out): # 清掉旧的显卡图,避免留下不再使用的文件
|
||||
if f.startswith('gpu_'):
|
||||
os.remove(os.path.join(out, f))
|
||||
for name, make in SPRITES.items():
|
||||
canvas = make()
|
||||
check_cells(canvas, name)
|
||||
canvas.png(os.path.join(out, name + '.png'))
|
||||
for name, make in OVERLAYS.items():
|
||||
make().png(os.path.join(out, name + '.png'))
|
||||
for name, make in UI_ICONS.items():
|
||||
make().png(os.path.join(out, name + '.png'))
|
||||
import big, big_cases
|
||||
for name, make in big.BIG.items():
|
||||
make().png(os.path.join(out, name + '.png'))
|
||||
for name, make in big_cases.CASES.items():
|
||||
if name.startswith('gpu_big_ov_fan_'):
|
||||
continue
|
||||
if not name.startswith('gpu_big_ov_print_') and name in ('gpu_big_ov_fin_dim', 'gpu_big_ov_fin_oxide', 'gpu_big_ov_brk_scratch', 'gpu_big_ov_seal_missing'):
|
||||
make().png(os.path.join(out, name + '.png'))
|
||||
# 风扇叠加按风扇数各出一套:叠加模块里的风扇位置是模块级变量,换成对应布局后再画
|
||||
for count, (centres, radius) in big.FAN_LAYOUT.items():
|
||||
big_cases.FANS = list(centres) if len(centres) > 1 else [centres[0], centres[0]]
|
||||
big_cases.FR = radius
|
||||
for fname, short in (('fan_dust1', 'fan_dust1'), ('fan_dust2', 'fan_dust2'), ('fan_chip', 'fan_chip')):
|
||||
getattr(big_cases, fname)().png(os.path.join(out, 'gpu_big_ov_%s_%d.png' % (short, count)))
|
||||
for m in MODELS:
|
||||
for style in ('normal', 'skew', 'stamp'):
|
||||
big_cases.print_overlay(m, style).png(os.path.join(out, 'gpu_big_ov_print_%s_%s.png' % (style, key(m))))
|
||||
print(out)
|
||||
@@ -5,8 +5,12 @@ namespace Decentralized.Domain
|
||||
public enum Venue { Exchange, Dex, Darknet }
|
||||
|
||||
/// <summary>
|
||||
/// 一个交易对 = 一个恒定乘积池(x·y = k)。Base 是被交易的币,Quote 是计价币;价格 = Quote 储备 / Base 储备。
|
||||
/// 每个交易对各有深度;夜间由 NPC 套利者把价格按比例拉向目标价。
|
||||
/// 一个交易对。DEX 是恒定乘积池(x·y = k):Base 是被交易的币,Quote 是计价币,价格 = Quote 储备 / Base 储备。
|
||||
/// Poinbase 主池是订单簿(<see cref="Book"/>):价格只取决于当天的累计净买入量,冲击随单子变大而增长得比线性慢
|
||||
/// (价格 = 参考价 × exp(κ · sign(x) · |x|^α),x = 净买入的名义价值 / 深度),拆单不占便宜,同量买进再卖出回到原价。
|
||||
/// 稳定币对(<see cref="Stable"/>)是 StableSwap 池(Curve 的曲线,放大系数 A):挂钩附近几乎没有滑点,偏离越大越接近恒定乘积;
|
||||
/// 储备按"价值单位"记(Base 数量 × 挂钩价),挂钩价夜里随参考价重设。
|
||||
/// 每个交易对各有深度;夜间由 NPC 套利者把价格按比例拉向目标价,订单簿的累计量清零。
|
||||
/// </summary>
|
||||
public sealed class Pool
|
||||
{
|
||||
@@ -14,10 +18,87 @@ namespace Decentralized.Domain
|
||||
public Venue Venue;
|
||||
public double BaseReserve, QuoteReserve;
|
||||
public double Fee;
|
||||
/// <summary>订单簿模式:参考价、当天累计净买入的 Base 数量、深度(Quote)。</summary>
|
||||
public bool Book;
|
||||
public double Ref, Net, Depth;
|
||||
/// <summary>StableSwap 模式:放大系数、挂钩价(储备里 Base 一侧按 数量 × 挂钩价 记)。</summary>
|
||||
public bool Stable;
|
||||
public double Amp, Peg;
|
||||
|
||||
public string Id => $"{Venue}:{Base}/{Quote}";
|
||||
|
||||
public double Price => QuoteReserve / BaseReserve;
|
||||
public double Price => Book ? PriceAt(Net) : Stable ? Peg * StableSlope(BaseReserve, QuoteReserve) : QuoteReserve / BaseReserve;
|
||||
|
||||
public static Pool CreateStable(Venue venue, string baseAsset, string quote, double price, double depth, double fee, double amp) =>
|
||||
new Pool { Venue = venue, Base = baseAsset, Quote = quote, Stable = true, Amp = amp, Peg = price, BaseReserve = depth, QuoteReserve = depth, Fee = fee };
|
||||
|
||||
// ——— StableSwap(两个币):Ann(x + y) + D = Ann·D + D³ / (4xy),Ann = 4A ———
|
||||
|
||||
private double Ann => 4 * Amp;
|
||||
|
||||
private double StableD(double x, double y)
|
||||
{
|
||||
double s = x + y, d = s;
|
||||
if (s <= 0) return 0;
|
||||
for (int i = 0; i < 255; i++)
|
||||
{
|
||||
double dp = d * d * d / (4 * x * y), prev = d;
|
||||
d = (Ann * s + 2 * dp) * d / ((Ann - 1) * d + 3 * dp);
|
||||
if (Math.Abs(d - prev) <= 1e-12 * d) break;
|
||||
}
|
||||
return d;
|
||||
}
|
||||
|
||||
/// <summary>已知一侧储备 x 和不变量 D,求另一侧。</summary>
|
||||
private double StableOther(double x, double d)
|
||||
{
|
||||
double c = d * d / (2 * x) * d / (2 * Ann), b = x + d / Ann, y = d;
|
||||
for (int i = 0; i < 255; i++)
|
||||
{
|
||||
double prev = y;
|
||||
y = (y * y + c) / (2 * y + b - d);
|
||||
if (Math.Abs(y - prev) <= 1e-12 * y) break;
|
||||
}
|
||||
return y;
|
||||
}
|
||||
|
||||
/// <summary>边际价格(每个价值单位的 Base 换多少 Quote):不变量对两侧偏导之比。平衡时为 1。</summary>
|
||||
private double StableSlope(double x, double y)
|
||||
{
|
||||
double d = StableD(x, y), d3 = d * d * d;
|
||||
return (Ann + d3 / (4 * x * x * y)) / (Ann + d3 / (4 * x * y * y));
|
||||
}
|
||||
|
||||
public static Pool CreateBook(Venue venue, string baseAsset, string quote, double price, double depth, double fee) =>
|
||||
new Pool { Venue = venue, Base = baseAsset, Quote = quote, Book = true, Ref = price, Depth = depth, Fee = fee };
|
||||
|
||||
private double PriceAt(double net)
|
||||
{
|
||||
double x = net * Ref / Depth;
|
||||
return Ref * Math.Exp(Math.Sign(x) * Tuning.BookK * Math.Pow(Math.Abs(x), Tuning.BookAlpha));
|
||||
}
|
||||
|
||||
/// <summary>订单簿上累计净买入从 a 走到 b 的成交额(Quote,不含手续费;b < a 为负)。辛普森积分,同一区间正反两个方向结果互为相反数。</summary>
|
||||
private double Cost(double a, double b)
|
||||
{
|
||||
const int n = 128;
|
||||
double h = (b - a) / n, sum = PriceAt(a) + PriceAt(b);
|
||||
for (int i = 1; i < n; i++) sum += PriceAt(a + i * h) * (i % 2 == 1 ? 4 : 2);
|
||||
return sum * h / 3;
|
||||
}
|
||||
|
||||
/// <summary>订单簿:花 quote(不含手续费)能买到多少 Base。牛顿迭代解 Cost(Net, Net + b) = quote。</summary>
|
||||
private double BookBaseFor(double quote)
|
||||
{
|
||||
double b = quote / Price;
|
||||
for (int i = 0; i < 30; i++)
|
||||
{
|
||||
double step = (Cost(Net, Net + b) - quote) / PriceAt(Net + b);
|
||||
b = Math.Max(0, b - step);
|
||||
if (Math.Abs(step) < 1e-10 * (1 + b)) break;
|
||||
}
|
||||
return b;
|
||||
}
|
||||
|
||||
public static Pool Create(Venue venue, string baseAsset, string quote, double price, double quoteDepth, double fee) =>
|
||||
new Pool { Venue = venue, Base = baseAsset, Quote = quote, QuoteReserve = quoteDepth, BaseReserve = quoteDepth / price, Fee = fee };
|
||||
@@ -25,6 +106,8 @@ namespace Decentralized.Domain
|
||||
/// <summary>预估:卖出 baseIn 个 Base 能得到多少 Quote(不改池子)。</summary>
|
||||
public double QuoteOut(double baseIn)
|
||||
{
|
||||
if (Book) return baseIn > 0 ? Cost(Net - baseIn, Net) * (1 - Fee) : 0;
|
||||
if (Stable) return baseIn > 0 ? QuoteReserve - StableOther(BaseReserve + baseIn * Peg * (1 - Fee), StableD(BaseReserve, QuoteReserve)) : 0;
|
||||
double x = BaseReserve + baseIn * (1 - Fee);
|
||||
return QuoteReserve - BaseReserve * QuoteReserve / x;
|
||||
}
|
||||
@@ -32,15 +115,33 @@ namespace Decentralized.Domain
|
||||
/// <summary>预估:花 quoteIn 个 Quote 能买到多少 Base(不改池子)。</summary>
|
||||
public double BaseOut(double quoteIn)
|
||||
{
|
||||
if (Book) return quoteIn > 0 ? BookBaseFor(quoteIn * (1 - Fee)) : 0;
|
||||
if (Stable) return quoteIn > 0 ? (BaseReserve - StableOther(QuoteReserve + quoteIn * (1 - Fee), StableD(BaseReserve, QuoteReserve))) / Peg : 0;
|
||||
double y = QuoteReserve + quoteIn * (1 - Fee);
|
||||
return BaseReserve - BaseReserve * QuoteReserve / y;
|
||||
}
|
||||
|
||||
/// <summary>预估:买到 baseOut 个 Base 要付多少 Quote(含手续费,不改池子);超出池子储备返回 +∞。</summary>
|
||||
public double QuoteIn(double baseOut)
|
||||
{
|
||||
if (baseOut <= 0) return 0;
|
||||
if (Book) return Cost(Net, Net + baseOut) / (1 - Fee);
|
||||
if (Stable)
|
||||
{
|
||||
double x = BaseReserve - baseOut * Peg;
|
||||
return x <= 0 ? double.PositiveInfinity : (StableOther(x, StableD(BaseReserve, QuoteReserve)) - QuoteReserve) / (1 - Fee);
|
||||
}
|
||||
if (baseOut >= BaseReserve) return double.PositiveInfinity;
|
||||
return (BaseReserve * QuoteReserve / (BaseReserve - baseOut) - QuoteReserve) / (1 - Fee);
|
||||
}
|
||||
|
||||
/// <summary>卖出 Base,返回得到的 Quote。手续费留在池里。</summary>
|
||||
public double SellBase(double baseIn)
|
||||
{
|
||||
if (baseIn <= 0) return 0;
|
||||
double out_ = QuoteOut(baseIn);
|
||||
if (Book) { Net -= baseIn; return out_; }
|
||||
if (Stable) { BaseReserve += baseIn * Peg; QuoteReserve -= out_; return out_; }
|
||||
BaseReserve += baseIn;
|
||||
QuoteReserve -= out_;
|
||||
return out_;
|
||||
@@ -51,6 +152,8 @@ namespace Decentralized.Domain
|
||||
{
|
||||
if (quoteIn <= 0) return 0;
|
||||
double out_ = BaseOut(quoteIn);
|
||||
if (Book) { Net += out_; return out_; }
|
||||
if (Stable) { QuoteReserve += quoteIn; BaseReserve -= out_ * Peg; return out_; }
|
||||
QuoteReserve += quoteIn;
|
||||
BaseReserve -= out_;
|
||||
return out_;
|
||||
@@ -60,6 +163,13 @@ namespace Decentralized.Domain
|
||||
public double ImpactOfBuy(double quoteIn)
|
||||
{
|
||||
double before = Price;
|
||||
if (Book) return PriceAt(Net + BaseOut(quoteIn)) / before - 1;
|
||||
if (Stable)
|
||||
{
|
||||
var copy = (Pool)MemberwiseClone();
|
||||
copy.BuyBase(quoteIn);
|
||||
return copy.Price / before - 1;
|
||||
}
|
||||
double y = QuoteReserve + quoteIn * (1 - Fee);
|
||||
double x = BaseReserve * QuoteReserve / y;
|
||||
return (y / x) / before - 1;
|
||||
@@ -77,6 +187,8 @@ namespace Decentralized.Domain
|
||||
|
||||
public void SetPrice(double price, double quoteDepth)
|
||||
{
|
||||
if (Book) { Ref = price; Net = 0; Depth = quoteDepth; return; }
|
||||
if (Stable) { Peg = price; BaseReserve = quoteDepth; QuoteReserve = quoteDepth; return; }
|
||||
QuoteReserve = quoteDepth;
|
||||
BaseReserve = quoteDepth / price;
|
||||
}
|
||||
|
||||
@@ -0,0 +1,44 @@
|
||||
using System;
|
||||
|
||||
namespace Decentralized.Domain
|
||||
{
|
||||
/// <summary>
|
||||
/// RatDigg 矿机暴毙后的修理:往机器的修理槽里按顺序放电子元件,约占机价的 4%。每一步只收这一步需要的那种元件,攒够这一步再进下一步,
|
||||
/// 全部攒够就修好(健康扣 <see cref="Tuning.AsicRepairHealthCut"/> 点)。游戏里电子元件的价值是 33 / 350 / 2,500(普通 / 稀有 / 超科技)。
|
||||
/// </summary>
|
||||
public static class AsicRepair
|
||||
{
|
||||
public static (string Item, int Count)[] Steps(string model)
|
||||
{
|
||||
switch (model)
|
||||
{
|
||||
case "M1": return new[] { ("common_electronic", 4), ("rare_electronic", 1) };
|
||||
case "M2": return new[] { ("rare_electronic", 2) };
|
||||
case "M3": return new[] { ("hypertech_electronic", 1), ("rare_electronic", 1) };
|
||||
default: throw new ArgumentOutOfRangeException(nameof(model));
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>当前这一步需要的元件;已修好(step 越界)返回 null。</summary>
|
||||
public static (string Item, int Count)? Need(string model, int step)
|
||||
{
|
||||
var steps = Steps(model);
|
||||
return step < steps.Length ? steps[step] : ((string, int)?)null;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 投入 count 件 item:只收当前这一步需要的那种,攒够就进下一步。返回实际收下的件数;step 达到总步数表示修好了。
|
||||
/// </summary>
|
||||
public static int Insert(string model, ref int step, ref int progress, string item, int count)
|
||||
{
|
||||
var need = Need(model, step);
|
||||
if (need == null || count <= 0 || item != need.Value.Item) return 0;
|
||||
int take = Math.Min(count, need.Value.Count - progress);
|
||||
progress += take;
|
||||
if (progress >= need.Value.Count) { step++; progress = 0; }
|
||||
return take;
|
||||
}
|
||||
|
||||
public static bool Done(string model, int step) => step >= Steps(model).Length;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,177 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
|
||||
namespace Decentralized.Domain
|
||||
{
|
||||
/// <summary>货的种类:违禁品、高科技物品、显卡。</summary>
|
||||
public enum GoodKind { Contraband, Tech, Gpu, Goods }
|
||||
|
||||
/// <summary>黑市货架上的一种货。显卡的 Item 是 "gpu:型号",Model 是标称型号,FakeOf 非空表示背后是别的芯片(买家看不到)。</summary>
|
||||
public class BmGood
|
||||
{
|
||||
public string Item;
|
||||
public GoodKind Kind;
|
||||
public int Level;
|
||||
public int Price;
|
||||
public string Model, FakeOf;
|
||||
public double Health;
|
||||
}
|
||||
|
||||
/// <summary>现货柜台上的一件货:剩余件数、含溢价的单价(信用点)。</summary>
|
||||
public sealed class BmOffer : BmGood
|
||||
{
|
||||
public int Qty;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Web3 黑市:黑市派系在链上的实体。货架上主要是违禁品(档次随黑市声望放开),偶尔有高科技物品和显卡(加价),
|
||||
/// 现货只收币,脏币也收,付出去的币连同按比例的污点一起留在卖家那边;Ponero 兑换处把任意币兑成无法追踪的 Ponero(这部分价值的污点被清除),有每日额度和手续费。
|
||||
/// 镇压期间整个平台下线。
|
||||
/// </summary>
|
||||
public sealed partial class BlackMarket
|
||||
{
|
||||
public List<BmOffer> Offers = new List<BmOffer>();
|
||||
public int RefreshedDay = -999;
|
||||
/// <summary>Ponero 兑换处当天已兑换的价值(信用点)及其日期。</summary>
|
||||
public double DeskToday;
|
||||
public int DeskDay = -1;
|
||||
|
||||
/// <summary>违禁品池:游戏物品 id 与违禁等级(1 低、2 中、3 高)。都是能转手的货(枪械、钥匙卡、密码解序器芯片、爆炸物);弹药、毒品、药品玩家用不上,不上架。</summary>
|
||||
public static readonly KeyValuePair<string, int>[] Pool =
|
||||
{
|
||||
P("handmade_pistol", 1), P("printed_gun", 1), P("stun_baton", 1),
|
||||
P("eng_keycard", 1), P("med_keycard", 1), P("ser_keycard", 1), P("sup_keycard", 1), P("crypto_module_ser", 1), P("crypto_module_sup", 1),
|
||||
P("revolver", 2), P("heavy_handmade_pistol", 2), P("flashbang_grenade", 2), P("smoke_grenade", 2),
|
||||
P("sci_keycard", 2), P("sec_keycard", 2), P("crypto_module_eng", 2), P("crypto_module_med", 2),
|
||||
P("shotgun", 3), P("smg", 3), P("c4", 3), P("cmd_keycard", 3), P("crypto_module_sec", 3),
|
||||
};
|
||||
|
||||
/// <summary>高科技物品池(不是违禁品,黑市上要加价):矿机能用上的系统模组、能量电池、能量阵列,和矿架本身。</summary>
|
||||
public static readonly string[] TechPool =
|
||||
{
|
||||
"system_module_overclock", "system_module_performance", "system_module_quality", "system_module_eco", "system_module_efficiancy",
|
||||
"system_module_fineness", "system_module_streamlining", "energy_credit_ext", "energy_credit_hyp", "energy_credit_breeder",
|
||||
"powerblock", "module_extractor_advanced", "pd_rig",
|
||||
};
|
||||
|
||||
private static KeyValuePair<string, int> P(string id, int level) => new KeyValuePair<string, int>(id, level);
|
||||
|
||||
public static bool Open(int rep) => rep >= Tuning.BmOpenRep;
|
||||
public static int MaxLevel(int rep) => rep >= Tuning.BmHighRep ? 3 : rep >= Tuning.BmMidRep ? 2 : rep >= Tuning.BmOpenRep ? 1 : 0;
|
||||
public static bool DeskOpen(int rep) => rep >= Tuning.PoneroOpenRep;
|
||||
public static int StockCount(int rep) => Tuning.BmStockBase + (int)Math.Max(0, rep / Tuning.BmStockPerRep);
|
||||
|
||||
/// <summary>货的加价:违禁品 0,高科技、显卡各有额外加价(在现货溢价 / 订单折扣之外)。</summary>
|
||||
public static double Extra(GoodKind k) => k == GoodKind.Tech ? Tuning.BmTechMarkup : k == GoodKind.Gpu ? Tuning.BmGpuMarkup : 0;
|
||||
|
||||
/// <summary>现货单价(信用点):基础价 ×(1 + 溢价 + 货的加价)。</summary>
|
||||
public static int PriceOf(long baseValue, GoodKind k = GoodKind.Contraband) => (int)Math.Max(1, Math.Round(baseValue * (1 + Tuning.BmPremium + Extra(k))));
|
||||
|
||||
/// <summary>抽 count 种货:高科技(中档声望起)和显卡按概率换掉违禁品。value 给出游戏物品的基础价;显卡的基础价按标称型号与成色算。</summary>
|
||||
private List<BmGood> Roll(int count, int day, int rep, Rng rng, Func<string, long> value, Func<long, GoodKind, int> price)
|
||||
{
|
||||
var goods = new List<BmGood>();
|
||||
var pool = Pool.Where(x => x.Value <= MaxLevel(rep)).ToList();
|
||||
var tech = TechPool.ToList();
|
||||
var gpus = UsedDealers.Pool(day);
|
||||
for (int i = 0; i < count; i++)
|
||||
{
|
||||
double r = rng.NextDouble();
|
||||
if (r < Tuning.BmGpuChance)
|
||||
{
|
||||
bool fresh = rng.Chance(Tuning.BmGpuNew);
|
||||
var c = UsedDealers.Card(gpus, fresh ? 0 : Tuning.BmGpuFake, 0, rng);
|
||||
if (fresh) c.Health = 100;
|
||||
goods.Add(new BmGood { Item = "gpu:" + c.Model, Kind = GoodKind.Gpu, Level = 2, Model = c.Model, FakeOf = c.FakeOf, Health = c.Health, Price = price(CardValue.Of(c.Model, c.Health), GoodKind.Gpu) });
|
||||
}
|
||||
else if (r < Tuning.BmGpuChance + Tuning.BmTechChance && tech.Count > 0)
|
||||
{
|
||||
int k = rng.Range(0, tech.Count - 1);
|
||||
string id = tech[k];
|
||||
tech.RemoveAt(k);
|
||||
long v = value(id);
|
||||
if (v > 0) goods.Add(new BmGood { Item = id, Kind = GoodKind.Tech, Level = 3, Price = price(v, GoodKind.Tech) });
|
||||
}
|
||||
else if (pool.Count > 0)
|
||||
{
|
||||
int k = rng.Range(0, pool.Count - 1);
|
||||
var pick = pool[k];
|
||||
pool.RemoveAt(k);
|
||||
long v = value(pick.Key);
|
||||
if (v > 0) goods.Add(new BmGood { Item = pick.Key, Kind = GoodKind.Contraband, Level = pick.Value, Price = price(v, GoodKind.Contraband) });
|
||||
}
|
||||
}
|
||||
return goods;
|
||||
}
|
||||
|
||||
/// <summary>每周刷新一次(或首次开放时):按声望开放的档次抽 StockCount 种货,每种 1–3 件(高档与显卡、高科技 1 件)。</summary>
|
||||
public bool Refresh(int day, int rep, Rng rng, Func<string, long> value)
|
||||
{
|
||||
if (!Open(rep) || day - RefreshedDay < Tuning.BmRefreshDays) return false;
|
||||
RefreshedDay = day;
|
||||
Offers.Clear();
|
||||
foreach (var g in Roll(StockCount(rep), day, rep, rng, value, PriceOf))
|
||||
Offers.Add(new BmOffer { Item = g.Item, Kind = g.Kind, Level = g.Level, Price = g.Price, Model = g.Model, FakeOf = g.FakeOf, Health = g.Health, Qty = g.Kind != GoodKind.Contraband || g.Level == 3 ? 1 : rng.Range(1, Tuning.BmSpotQtyMax) });
|
||||
return true;
|
||||
}
|
||||
|
||||
/// <summary>买一件:付 asset 币。钱包里按价值比例带走的污点和成本留在卖家那边。成功返回 true,库存减一。</summary>
|
||||
public bool Buy(BmOffer o, Wallet w, string asset, Func<string, double> price)
|
||||
{
|
||||
if (o == null || o.Qty <= 0 || asset == Assets.CRC) return false;
|
||||
double p = price(asset);
|
||||
if (p <= 0) return false;
|
||||
double qty = o.Price / p;
|
||||
if (w.Avail(asset) + 1e-9 < qty) return false;
|
||||
double total = w.Value(price);
|
||||
double share = total > 0 ? Math.Min(1, o.Price / total) : 0;
|
||||
w.Taint -= w.Taint * share;
|
||||
w.Basis -= w.Basis * share;
|
||||
w.Add(asset, -qty);
|
||||
o.Qty--;
|
||||
if (o.Qty <= 0) Offers.Remove(o);
|
||||
return true;
|
||||
}
|
||||
|
||||
/// <summary>Ponero 对信用点的价格:跟随 PSC。</summary>
|
||||
public static double PoneroPrice(double pscPrice) => pscPrice * Tuning.PoneroPscRatio;
|
||||
|
||||
public double DeskLeft(int day) => Math.Max(0, Tuning.PoneroDailyCap - (DeskDay == day ? DeskToday : 0));
|
||||
|
||||
/// <summary>兑入 Ponero:from 币 amount 个,扣手续费后按 Ponero 价到账;这部分价值带的污点被清除(不跟着 Ponero)。返回到账数量,额度或余额不足返回 -1。</summary>
|
||||
public double ToPonero(Wallet w, string from, double amount, int day, Func<string, double> price)
|
||||
{
|
||||
double value = amount * price(from);
|
||||
if (from == Assets.Ponero || amount <= 0 || value <= 0 || w.Avail(from) + 1e-9 < amount || value > DeskLeft(day) + 1e-9) return -1;
|
||||
double total = w.Value(price);
|
||||
double share = total > 0 ? Math.Min(1, value / total) : 0;
|
||||
w.Taint -= w.Taint * share;
|
||||
w.Add(from, -amount);
|
||||
double got = value * (1 - Tuning.PoneroFee) / price(Assets.Ponero);
|
||||
w.Add(Assets.Ponero, got);
|
||||
w.RecordBuy(Assets.Ponero, got, value);
|
||||
Spend(day, value);
|
||||
return got;
|
||||
}
|
||||
|
||||
/// <summary>Ponero 兑出成 to 币:手续费同上,计入当天额度。返回到账数量,不足返回 -1。</summary>
|
||||
public double FromPonero(Wallet w, string to, double amount, int day, Func<string, double> price)
|
||||
{
|
||||
double value = amount * price(Assets.Ponero);
|
||||
if (to == Assets.Ponero || amount <= 0 || value <= 0 || w.Avail(Assets.Ponero) + 1e-9 < amount || value > DeskLeft(day) + 1e-9 || price(to) <= 0) return -1;
|
||||
w.Add(Assets.Ponero, -amount);
|
||||
double got = value * (1 - Tuning.PoneroFee) / price(to);
|
||||
w.Add(to, got);
|
||||
w.RecordBuy(to, got, value);
|
||||
Spend(day, value);
|
||||
return got;
|
||||
}
|
||||
|
||||
private void Spend(int day, double value)
|
||||
{
|
||||
if (DeskDay != day) { DeskDay = day; DeskToday = 0; }
|
||||
DeskToday += value;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,91 @@
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
|
||||
namespace Decentralized.Domain
|
||||
{
|
||||
/// <summary>商家货架上的一项货:游戏物品 id、货的种类、违禁等级(只对违禁品有意义,随黑市声望放开)。</summary>
|
||||
public struct BmEntry
|
||||
{
|
||||
public string Id;
|
||||
public GoodKind Kind;
|
||||
public int Level;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 商家类型的货表。除了矿卡,其余都按玩家能走的路线配货:矿工、酿酒师、化学师、药剂师、枪械师、水培农场主、养殖户、水务、仓储、工具、奢侈品,
|
||||
/// 加上违禁品(军火、证件芯片)。大宗商家什么都卖。
|
||||
/// </summary>
|
||||
public static class Merchants
|
||||
{
|
||||
private static BmEntry C(string id, int level) => new BmEntry { Id = id, Kind = GoodKind.Contraband, Level = level };
|
||||
private static BmEntry T(string id) => new BmEntry { Id = id, Kind = GoodKind.Tech, Level = 3 };
|
||||
private static BmEntry G(string id) => new BmEntry { Id = id, Kind = GoodKind.Goods, Level = 0 };
|
||||
private static BmEntry[] Gs(params string[] ids) => ids.Select(G).ToArray();
|
||||
|
||||
public static readonly Dictionary<MerchantType, BmEntry[]> Table = new Dictionary<MerchantType, BmEntry[]>
|
||||
{
|
||||
[MerchantType.Rigs] = new[] { T("pd_rig"), T("energy_credit_ext"), T("energy_credit_hyp"), T("energy_credit_breeder"), T("powerblock"), T("recharger"), T("current_converter") },
|
||||
[MerchantType.Modules] = new[] { T("system_module_overclock"), T("system_module_performance"), T("system_module_quality"), T("system_module_eco"), T("system_module_efficiancy"),
|
||||
T("system_module_fineness"), T("system_module_streamlining"), T("module_extractor_advanced"), T("module_bay_expansion_kit") },
|
||||
[MerchantType.Arms] = new[] { C("handmade_pistol", 1), C("printed_gun", 1), C("stun_baton", 1), C("revolver", 2), C("heavy_handmade_pistol", 2), C("flashbang_grenade", 2), C("smoke_grenade", 2),
|
||||
C("shotgun", 3), C("smg", 3), C("c4", 3), G("combat_knife"), G("combat_machete"), G("hatchet"), G("crowbar"), G("kitchen_cleaver"), G("skinning_knife"), G("stun_gun"), G("tazer") },
|
||||
[MerchantType.GunMods] = Gs("silencer2", "laser2", "match_barrel", "trigger_group", "mag_10mm_high", "mag_22_high", "mag_10mm_smg_high", "rds", "compensator", "stock", "grip", "bipod", "barrel",
|
||||
"printer_chip_gun_part", "printer_chip_silencer", "printer_chip_handmade_pistol_frame", "printer_chip_heavy_handmade_pistol_frame", "printer_module_cnc", "printer_module_metal", "gun_part", "printer_plastic"),
|
||||
[MerchantType.Docs] = new[] { C("eng_keycard", 1), C("med_keycard", 1), C("ser_keycard", 1), C("sup_keycard", 1), C("crypto_module_ser", 1), C("crypto_module_sup", 1),
|
||||
C("sci_keycard", 2), C("sec_keycard", 2), C("crypto_module_eng", 2), C("crypto_module_med", 2), C("cmd_keycard", 3), C("crypto_module_sec", 3) },
|
||||
[MerchantType.Pharma] = new[] { C("unlicensed_phagimycin_pill", 2), C("dream_dust", 2), C("fanta_pill", 3), C("nightmare_dust", 3), C("zyanide_pill", 2),
|
||||
G("black_injector"), G("pure_white_injector"), G("large_purple_injector"), G("pink_injector"), G("pink_alt_injector"), G("blue_blood_bag"), G("surgery_tool"), G("zerochew"), G("phagimycin_pill") },
|
||||
[MerchantType.Chem] = new[] { C("restricted_chemical", 2), G("common_chemical"), G("flux_agent"), G("advanced_flux_agent"), G("chem_module"), G("evaporator_module_solvent_recovery"),
|
||||
G("chem_scanner"), G("med_bottle_blue"), G("med_bottle_orange"), G("med_bottle_red"), G("med_bottle_small_pink"), G("med_bottle_violet"), G("100ml_cylinder"), G("5ml_dropper") },
|
||||
[MerchantType.Brewer] = new[] { G("wine_yeast"), G("wine_superyeast"), G("wine_yeast_infinite"), C("wine_yeast_red", 1), G("wine_berry"), G("bloomberry_seed"), G("nudka"), G("red_beer"), G("beerCase"), G("wine_bottle") },
|
||||
[MerchantType.Farm] = new[] { G("nutrifruit_seed"), G("kotton_seed"), G("fillerweed_seed"), G("hydroreed_seed"), G("bloomberry_seed"), C("dream_cap_seed", 1),
|
||||
G("farm_module_nutrifruit"), G("farm_module_kotton_loom"), G("farm_module_fillerweed_production"), G("farm_module_hydroreed_filter"), G("farm_module_dream_cap"), G("farm_module_smuggler"),
|
||||
G("plant_analyser"), G("plant_dna_disk"), G("nutrient_tablet"), G("hydroreed_filter") },
|
||||
[MerchantType.Husbandry] = Gs("tilapia_roe", "sturgeon_roe", "caviar", "ras", "serum_green", "serum_red",
|
||||
"livestock_feed_dispenser", "auto_butcher", "industrial_fish_feed", "animal_cage"),
|
||||
[MerchantType.Miner] = Gs("common_ore", "rare_ore", "metal_ingot", "scrap_metal", "common_electronic", "rare_electronic", "hypertech_electronic", "metal_scanner", "wire", "advanced_flux_agent"),
|
||||
[MerchantType.Water] = Gs("water_filter_adv", "portable_water_purifier", "water_tank", "uv_filter", "water_tablet_container", "water_test_container", "aquascan", "bottled_water_premium", "water_jug", "water_ration"),
|
||||
[MerchantType.Storage] = Gs("smuggler_bay", "smuggler_bay_mod", "smuggler_bay_mini", "storage_bay_large", "storage_bay_expansion_kit", "hypertech_bay", "machine_bay_ext", "storage_bay_chem",
|
||||
"storage_bay_gun", "backpack_large_military"),
|
||||
[MerchantType.Tools] = Gs("turbo_booster", "turbo_booster_adv", "turbo_booster_hypertech", "welder", "xray_scanner", "magnifier", "labeler_blue", "toolbox", "wire_cutter", "mind_reprogrammer"),
|
||||
[MerchantType.Luxury] = new[] { C("pheromone_perfume", 2), G("neuroactive_perfume"), G("self_refilling_neuroactive_perfume"), G("skincare_cream"), G("packet_red_cigarette"), G("gamblers_coin"), G("kotton_fabric"), G("armor_lining") },
|
||||
};
|
||||
|
||||
/// <summary>
|
||||
/// 各类商家收的币:硬件和技术类收 PSC,违禁类收 CRT 和隐私币,农业养殖水务收 PSC 和 CRA,个人卖家收 CRT 和隐私币。
|
||||
/// 平台现货收 PSC、CRT、CRA。不在表里的币要先换:Web3 内置的自动换币要多付滑点(<see cref="Tuning.BmAutoSwapSlip"/>),也可以自己去 DEX 换。
|
||||
/// </summary>
|
||||
public static readonly string[] PlatformAccepts = { Assets.PSC, Assets.CRT, Assets.CRA };
|
||||
|
||||
public static string[] Accepts(MerchantType type)
|
||||
{
|
||||
switch (type)
|
||||
{
|
||||
case MerchantType.Rigs: case MerchantType.Modules: case MerchantType.Miner: case MerchantType.Tools: case MerchantType.Storage:
|
||||
case MerchantType.GpuNew: case MerchantType.GpuUsed: case MerchantType.Asic: case MerchantType.Elite: case MerchantType.Bulk:
|
||||
return new[] { Assets.PSC, Assets.CRT };
|
||||
case MerchantType.Arms: case MerchantType.GunMods: case MerchantType.Docs: case MerchantType.Pharma: case MerchantType.Chem:
|
||||
case MerchantType.Luxury: case MerchantType.Personal:
|
||||
return new[] { Assets.CRT, Assets.Ponero };
|
||||
default: // Brewer、Farm、Husbandry、Water
|
||||
return new[] { Assets.PSC, Assets.CRA };
|
||||
}
|
||||
}
|
||||
|
||||
private static readonly Dictionary<string, BmEntry> ById = BuildIndex();
|
||||
|
||||
private static Dictionary<string, BmEntry> BuildIndex()
|
||||
{
|
||||
var d = new Dictionary<string, BmEntry>();
|
||||
foreach (var e in Table.Values.SelectMany(x => x)) d[e.Id] = e;
|
||||
foreach (var kv in BlackMarket.Pool) d[kv.Key] = new BmEntry { Id = kv.Key, Kind = GoodKind.Contraband, Level = kv.Value };
|
||||
foreach (var id in BlackMarket.TechPool) d[id] = new BmEntry { Id = id, Kind = GoodKind.Tech, Level = 3 };
|
||||
return d;
|
||||
}
|
||||
|
||||
/// <summary>这个物品 id 在黑市上是不是一件货(现货柜台、商家货架里出现过的,都能转手出售)。</summary>
|
||||
public static bool IsGood(string id) => ById.ContainsKey(id);
|
||||
|
||||
public static BmEntry Info(string id) => ById[id];
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,356 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
|
||||
namespace Decentralized.Domain
|
||||
{
|
||||
public enum PayMode { Escrow, Advance }
|
||||
/// <summary>商家类型:矿卡(全新 / 二手)、矿架能源、模组、军火、枪匠配件、证件芯片、药物、化学、酿酒、水培、养殖、矿工、水务、仓储、工具、奢侈品;大宗商家、尖端店铺(只卖贵货,概率低)、个人卖家(什么都卖,价格随心所欲)随机出现。</summary>
|
||||
public enum MerchantType { GpuNew, GpuUsed, Rigs, Modules, Arms, GunMods, Docs, Pharma, Chem, Brewer, Farm, Husbandry, Miner, Water, Storage, Tools, Luxury, Bulk, Elite, Personal, Asic }
|
||||
public enum OrderState { Pending, Ready, Done, Refunded, Lost }
|
||||
|
||||
/// <summary>黑市上的卖家:成交数与好评率公开;是不是骗子是隐藏的。</summary>
|
||||
public sealed class BmSeller
|
||||
{
|
||||
public string Name;
|
||||
public int Trades;
|
||||
public int Rating; // 好评率 %
|
||||
public bool Scam;
|
||||
public MerchantType Type;
|
||||
/// <summary>商家的价格系数(订单价 = 基础价 × 系数,各家不同)。</summary>
|
||||
public double Factor;
|
||||
public int Days => Type == MerchantType.Bulk ? Tuning.BmBulkDays : Type == MerchantType.Elite ? Tuning.BmEliteDays : Tuning.BmDoorDays;
|
||||
/// <summary>只有成交数够多的卖家才接受提前放款。</summary>
|
||||
public bool Advance => Trades >= Tuning.BmAdvanceMinTrades;
|
||||
}
|
||||
|
||||
/// <summary>商家货架上的一种货:卖家、货、单价(订单价)、库存。</summary>
|
||||
public sealed class BmListing : BmGood
|
||||
{
|
||||
public int Seller;
|
||||
public int Qty;
|
||||
}
|
||||
|
||||
public sealed class BmOrder
|
||||
{
|
||||
public int Id;
|
||||
public string Item;
|
||||
public string Seller;
|
||||
public bool SellerScam;
|
||||
public PayMode Mode;
|
||||
public int Count = 1;
|
||||
public string Model, FakeOf;
|
||||
public double Health;
|
||||
public int Price;
|
||||
public string Asset;
|
||||
public double Qty;
|
||||
/// <summary>付款的钱包地址:退款回这里。</summary>
|
||||
public string Wallet;
|
||||
/// <summary>付款时留在卖家那边的污点与成本:退款时一并还回,免得"付脏币再退款"洗钱。</summary>
|
||||
public double Taint, Basis;
|
||||
public int PlacedDay, DueDay;
|
||||
/// <summary>被截获后执法选择了上门:到货时快递员是执法人员,签收即记罪证。</summary>
|
||||
public bool Controlled;
|
||||
public OrderState State = OrderState.Pending;
|
||||
/// <summary>终态的原因:done / scam / rug / intercept / theft / refund。</summary>
|
||||
public string Why;
|
||||
}
|
||||
|
||||
/// <summary>一笔会被追查的交易:到期日、金额(信用点)、来源(honeypot / seller / controlled)。</summary>
|
||||
public sealed class BmTrap
|
||||
{
|
||||
public int Day;
|
||||
public double Amount;
|
||||
public string Why;
|
||||
public string Item;
|
||||
/// <summary>对应的订单(没收到货的订单不会被追查);0 表示不挂订单(出售记录、落网)。</summary>
|
||||
public int OrderId;
|
||||
/// <summary>同一次蜜罐 / 同一次落网的追查归为一组,累计记罪证有上限。</summary>
|
||||
public int Group;
|
||||
}
|
||||
|
||||
/// <summary>夜间发生的订单事件,供日志与新闻使用。</summary>
|
||||
public sealed class BmEvent
|
||||
{
|
||||
public string Kind; // ready / scam_refund / scam_loss / rug / intercept / reopen
|
||||
public BmOrder Order;
|
||||
public BmSale Sale;
|
||||
public double Amount;
|
||||
}
|
||||
|
||||
public sealed partial class BlackMarket
|
||||
{
|
||||
public List<BmSeller> Sellers = new List<BmSeller>();
|
||||
public List<BmListing> Catalog = new List<BmListing>();
|
||||
public List<BmOrder> Orders = new List<BmOrder>();
|
||||
public List<string> Forum = new List<string>();
|
||||
/// <summary>平台跑路后关闭到这一天(含)。</summary>
|
||||
public int ClosedUntil = -1;
|
||||
/// <summary>执法接管平台的最后一天(含);期间的交易之后会被追查。</summary>
|
||||
public int HoneypotUntil = -1;
|
||||
public int HoneypotStart = -1;
|
||||
/// <summary>每组追查已经记过的罪证。</summary>
|
||||
public Dictionary<int, double> Charged = new Dictionary<int, double>();
|
||||
public List<BmTrap> Traps = new List<BmTrap>();
|
||||
public int NextOrderId = 1;
|
||||
|
||||
/// <summary>订单没有交付(退款、被截获、骗子、平台跑路、拒签、被查封):对应的追查一并取消。</summary>
|
||||
private void DropTraps(BmOrder o) => Traps.RemoveAll(t => t.OrderId == o.Id && o.Id != 0);
|
||||
|
||||
public bool Honeypot(int day) => day <= HoneypotUntil;
|
||||
|
||||
public static double HoneypotChance(int secRep) => Math.Min(Tuning.BmHoneypotMax, Tuning.BmHoneypotBase + Math.Max(0, secRep) * Tuning.BmHoneypotPerSecRep);
|
||||
|
||||
|
||||
public bool Closed(int day) => day <= ClosedUntil;
|
||||
|
||||
/// <summary>托管中和已提前放款但尚未交付的资金(信用点),平台跑路的概率随它增加。</summary>
|
||||
public double Held => Orders.Where(o => o.State == OrderState.Pending).Sum(o => (double)o.Price) + HeldSales;
|
||||
|
||||
/// <summary>批量折扣:一次订 5 件以上 95 折,10 件以上 9 折。</summary>
|
||||
public static double BulkDiscount(int count) => count >= Tuning.BmBulk2Count ? Tuning.BmBulk2Discount : count >= Tuning.BmBulk1Count ? Tuning.BmBulk1Discount : 0;
|
||||
public static int OrderTotal(int unit, int count) => (int)Math.Max(1, Math.Round(unit * count * (1 - BulkDiscount(count))));
|
||||
public static int EscrowFee(int price) => (int)Math.Ceiling(price * Tuning.BmEscrowFee);
|
||||
/// <summary>下单实付(信用点):托管 = 订单价 + 托管费;提前放款 = 订单价打折。</summary>
|
||||
public static int Pay(int price, PayMode m) => m == PayMode.Escrow ? price + EscrowFee(price) : (int)Math.Round(price * (1 - Tuning.BmAdvanceDiscount));
|
||||
|
||||
public double RugChance => Scales.R(Math.Min(Tuning.BmRugMax, Tuning.BmRugBase + Held / 10000.0 * Tuning.BmRugPerTenK));
|
||||
|
||||
/// <summary>每周必有的"矿工路线"商家类型(从中抽 2 家),其余按全部类型抽。</summary>
|
||||
private static readonly MerchantType[] Core = { MerchantType.GpuNew, MerchantType.GpuUsed, MerchantType.Rigs, MerchantType.Modules };
|
||||
private static readonly MerchantType[] Others = { MerchantType.Arms, MerchantType.GunMods, MerchantType.Docs, MerchantType.Pharma, MerchantType.Chem, MerchantType.Brewer,
|
||||
MerchantType.Farm, MerchantType.Husbandry, MerchantType.Miner, MerchantType.Water, MerchantType.Storage, MerchantType.Tools, MerchantType.Luxury };
|
||||
|
||||
private static double F(Rng rng, double lo, double hi) => lo + rng.NextDouble() * (hi - lo);
|
||||
|
||||
private static List<BmEntry> AllEntries() => Merchants.Table.Values.SelectMany(x => x).GroupBy(x => x.Id).Select(g => g.First()).ToList();
|
||||
|
||||
private static string[] HighGpus => Hardware.Specs.Values.Where(x => !x.Asic && !x.Scrap && x.Tier >= Tuning.BmEliteGpuTier).Select(x => x.Model).ToArray();
|
||||
|
||||
/// <summary>商家类型对应的货(含货种、库存),违禁品按声望放开等级。个人卖家什么都卖、每件各自定价;尖端店铺只卖贵货。</summary>
|
||||
private List<BmListing> MerchantGoods(int idx, BmSeller s, int day, int rep, Rng rng, Func<string, long> value)
|
||||
{
|
||||
var list = new List<BmListing>();
|
||||
if (s.Type == MerchantType.Asic) return AsicGoods(idx, s, rep, rng);
|
||||
bool gpuKind = s.Type == MerchantType.GpuNew || s.Type == MerchantType.GpuUsed;
|
||||
int n = s.Type == MerchantType.Bulk ? 2 : s.Type == MerchantType.Elite ? Tuning.BmEliteListings : s.Type == MerchantType.Personal ? Tuning.BmPersonalListings : Tuning.BmMerchantListings;
|
||||
List<BmEntry> entries = gpuKind ? new List<BmEntry>() : s.Type == MerchantType.Bulk || s.Type == MerchantType.Personal || s.Type == MerchantType.Elite ? AllEntries() : Merchants.Table[s.Type].ToList();
|
||||
entries = entries.Where(e => e.Kind != GoodKind.Contraband || e.Level <= MaxLevel(rep)).ToList();
|
||||
var gpus = UsedDealers.Pool(day);
|
||||
for (int i = 0; i < n; i++)
|
||||
{
|
||||
int qty = s.Type == MerchantType.Bulk ? rng.Range(Tuning.BmBulkQtyMin, Tuning.BmBulkQtyMax)
|
||||
: s.Type == MerchantType.Elite ? rng.Range(1, Tuning.BmEliteQtyMax)
|
||||
: s.Type == MerchantType.Personal ? rng.Range(1, Tuning.BmPersonalQtyMax)
|
||||
: s.Type == MerchantType.GpuNew ? rng.Range(Math.Max(1, Tuning.BmQtyMin - Tuning.BmNewGpuQtyMinCut), Tuning.BmQtyMax - Tuning.BmNewGpuQtyMaxCut) : rng.Range(Tuning.BmQtyMin, Tuning.BmQtyMax);
|
||||
double factor = s.Type == MerchantType.Personal ? F(rng, Tuning.BmPersonalFactorMin, Tuning.BmPersonalFactorMax) : s.Factor * F(rng, 1 - Tuning.BmPriceJitter, 1 + Tuning.BmPriceJitter);
|
||||
BmListing l = null;
|
||||
bool eliteGpu = s.Type == MerchantType.Elite && rng.Chance(Tuning.BmEliteGpuChance);
|
||||
bool personalGpu = s.Type == MerchantType.Personal && rng.Chance(Tuning.BmPersonalGpuChance);
|
||||
if (gpuKind || eliteGpu || personalGpu)
|
||||
{
|
||||
bool fresh = s.Type == MerchantType.GpuNew || eliteGpu || (personalGpu && rng.Chance(Tuning.BmPersonalGpuNew));
|
||||
var pool = eliteGpu ? HighGpus : gpus;
|
||||
var c = UsedDealers.Card(pool, fresh ? 0 : Tuning.BmGpuFake, 0, rng);
|
||||
if (fresh) c.Health = 100;
|
||||
l = new BmListing { Item = "gpu:" + c.Model, Kind = GoodKind.Gpu, Level = 2, Model = c.Model, FakeOf = c.FakeOf, Health = c.Health, Price = (int)Math.Max(1, Math.Round(CardValue.Of(c.Model, c.Health) * factor)) };
|
||||
}
|
||||
else
|
||||
{
|
||||
bool wantElite = s.Type == MerchantType.Elite || (s.Type == MerchantType.Personal && rng.Chance(Tuning.BmPersonalEliteShare));
|
||||
BmEntry pick = default; long v = 0; bool found = false;
|
||||
for (int tries = 0; tries < 40 && entries.Count > 0 && !found; tries++)
|
||||
{
|
||||
int k = rng.Range(0, entries.Count - 1);
|
||||
var e = entries[k];
|
||||
long val = value(e.Id);
|
||||
if (val <= 0) { entries.RemoveAt(k); continue; }
|
||||
bool ok = s.Type == MerchantType.Elite ? val >= Tuning.BmEliteMinValue : wantElite ? val > Tuning.BmMaxUnitValue : val <= Tuning.BmMaxUnitValue;
|
||||
if (!ok) continue;
|
||||
pick = e; v = val; found = true; entries.RemoveAt(k);
|
||||
}
|
||||
if (!found) continue;
|
||||
l = new BmListing { Item = pick.Id, Kind = pick.Kind, Level = pick.Level, Price = (int)Math.Max(1, Math.Round(v * factor)) };
|
||||
}
|
||||
l.Seller = idx; l.Qty = qty;
|
||||
list.Add(l);
|
||||
}
|
||||
return list;
|
||||
}
|
||||
|
||||
public static int AsicRep(string model) => model == "M3" ? Tuning.AsicRepM3 : model == "M2" ? Tuning.AsicRepM2 : Tuning.AsicRepM1;
|
||||
private static double AsicWeight(string model) => model == "M3" ? Tuning.AsicWeightM3 : model == "M2" ? Tuning.AsicWeightM2 : Tuning.AsicWeightM1;
|
||||
|
||||
/// <summary>矿机商:一台 RatDigg 矿机,型号按黑市声望放开,新机(70%)或二手;价格 = 机价(二手按健康度折算)× 商家系数。</summary>
|
||||
private List<BmListing> AsicGoods(int idx, BmSeller s, int rep, Rng rng)
|
||||
{
|
||||
var models = new[] { "M1", "M2", "M3" }.Where(m => rep >= AsicRep(m)).ToList();
|
||||
if (models.Count == 0) return new List<BmListing>();
|
||||
double roll = rng.NextDouble() * models.Sum(AsicWeight);
|
||||
string model = models.Last();
|
||||
foreach (var m in models) { roll -= AsicWeight(m); if (roll <= 0) { model = m; break; } }
|
||||
bool fresh = rng.Chance(Tuning.AsicNewShare);
|
||||
double health = fresh ? 100 : rng.Range(Tuning.AsicUsedHealthMin, Tuning.AsicUsedHealthMax);
|
||||
double factor = s.Factor * F(rng, 1 - Tuning.BmPriceJitter, 1 + Tuning.BmPriceJitter);
|
||||
return new List<BmListing>
|
||||
{
|
||||
new BmListing { Seller = idx, Item = "gpu:" + model, Kind = GoodKind.Gpu, Level = 2, Model = model, Health = health, Qty = model == "M1" ? rng.Range(1, 2) : 1,
|
||||
Price = (int)Math.Max(1, Math.Round(CardValue.Of(model, health) * factor)) },
|
||||
};
|
||||
}
|
||||
|
||||
/// <summary>每周重新生成商家、货架和论坛情报(与现货同一天刷新):从 6 种类型里抽 BmMerchantCount 家,另有概率出现一家大宗商家。</summary>
|
||||
public void RefreshOrders(int day, int rep, Rng rng, Func<string, long> value, bool allTypes = false)
|
||||
{
|
||||
Sellers.Clear(); Catalog.Clear(); Forum.Clear();
|
||||
var types = Core.OrderBy(_ => rng.NextDouble()).Take(Tuning.BmCoreMerchants).ToList();
|
||||
types.AddRange(Others.OrderBy(_ => rng.NextDouble()).Take(Tuning.BmMerchantCount - Tuning.BmCoreMerchants));
|
||||
if (allTypes) { types = ((MerchantType[])Enum.GetValues(typeof(MerchantType))).ToList(); types.Add(MerchantType.Personal); }
|
||||
else
|
||||
{
|
||||
if (rng.Chance(Tuning.BmBulkChance)) types.Add(MerchantType.Bulk);
|
||||
if (rng.Chance(Tuning.BmEliteChance)) types.Add(MerchantType.Elite);
|
||||
if (rep >= Tuning.AsicRepM1 && rng.Chance(Tuning.AsicChance)) types.Add(MerchantType.Asic);
|
||||
for (int i = 0; i < Tuning.BmPersonalCount; i++) types.Add(MerchantType.Personal);
|
||||
}
|
||||
foreach (var t in types)
|
||||
{
|
||||
bool personal = t == MerchantType.Personal;
|
||||
bool scam = rng.Chance(personal ? Tuning.BmPersonalScam : Tuning.BmScamSellerShare);
|
||||
// 骗子多半是新号,也有刷过好评的老号;个人卖家都是新号
|
||||
bool fresh = personal || (scam ? rng.Chance(Tuning.BmScamFresh) : rng.Chance(Tuning.BmHonestFresh));
|
||||
double lo = t == MerchantType.Elite || t == MerchantType.Asic ? Tuning.BmFactorEliteMin : t == MerchantType.GpuNew ? Tuning.BmFactorNewMin : t == MerchantType.GpuUsed ? Tuning.BmFactorUsedMin : t == MerchantType.Bulk ? Tuning.BmFactorBulkMin : Tuning.BmFactorMin;
|
||||
double hi = t == MerchantType.Elite || t == MerchantType.Asic ? Tuning.BmFactorEliteMax : t == MerchantType.GpuNew ? Tuning.BmFactorNewMax : t == MerchantType.GpuUsed ? Tuning.BmFactorUsedMax : t == MerchantType.Bulk ? Tuning.BmFactorBulkMax : Tuning.BmFactorMax;
|
||||
var s = new BmSeller
|
||||
{
|
||||
Name = ChainAddress.Make(rng.NextUInt()),
|
||||
Scam = scam, Type = t, Factor = personal ? 1.0 : F(rng, lo, hi),
|
||||
Trades = fresh ? rng.Range(0, Tuning.BmFreshTradesMax) : rng.Range(Tuning.BmOldTradesMin, Tuning.BmOldTradesMax),
|
||||
Rating = scam && !fresh ? rng.Range(Tuning.BmScamOldRatingMin, Tuning.BmScamOldRatingMax) : fresh ? rng.Range(Tuning.BmFreshRatingMin, Tuning.BmFreshRatingMax) : rng.Range(Tuning.BmOldRatingMin, Tuning.BmOldRatingMax),
|
||||
};
|
||||
Sellers.Add(s);
|
||||
if (scam && rng.Chance(Tuning.BmForumScamHint)) Forum.Add("scam:" + s.Name);
|
||||
}
|
||||
for (int i = 0; i < Sellers.Count; i++) Catalog.AddRange(MerchantGoods(i, Sellers[i], day, rep, rng, value));
|
||||
if (RugChance > Scales.R(Tuning.BmRugBase * Tuning.BmForumRugFactor)) Forum.Add("rug");
|
||||
}
|
||||
|
||||
/// <summary>目录里全部货按订单价算的总值(信用点),用来核对每周周转量。</summary>
|
||||
public double CatalogValue => Catalog.Sum(l => (double)l.Price * l.Qty);
|
||||
|
||||
/// <summary>下单:钱包里的币按实付折算扣除,污点与成本按比例留在卖家那边(记在订单上)。成功返回订单。</summary>
|
||||
public BmOrder Place(BmListing l, int count, PayMode mode, Wallet w, string asset, int day, Func<string, double> price)
|
||||
{
|
||||
if (l == null || count < 1 || count > l.Qty || asset == Assets.CRC || Closed(day)) return null;
|
||||
var seller = Sellers[l.Seller];
|
||||
if (mode == PayMode.Advance && !seller.Advance) return null;
|
||||
double p = price(asset);
|
||||
if (p <= 0) return null;
|
||||
int credits = Pay(OrderTotal(l.Price, count), mode);
|
||||
double qty = credits / p;
|
||||
if (w.Avail(asset) + 1e-9 < qty) return null;
|
||||
double total = w.Value(price);
|
||||
double share = total > 0 ? Math.Min(1, credits / total) : 0;
|
||||
double taint = w.Taint * share, basis = w.Basis * share;
|
||||
w.Taint -= taint; w.Basis -= basis;
|
||||
w.Add(asset, -qty);
|
||||
var o = new BmOrder
|
||||
{
|
||||
Id = NextOrderId++, Item = l.Item, Seller = seller.Name, SellerScam = seller.Scam, Mode = mode, Count = count, Model = l.Model, FakeOf = l.FakeOf, Health = l.Health, Price = credits, Asset = asset, Qty = qty,
|
||||
Taint = taint, Basis = basis, PlacedDay = day, DueDay = day + seller.Days, Wallet = w.Address,
|
||||
};
|
||||
l.Qty -= count;
|
||||
if (l.Qty <= 0) Catalog.Remove(l);
|
||||
Orders.Add(o);
|
||||
if (Honeypot(day)) Traps.Add(new BmTrap { Day = day + Tuning.BmTrapDelay, Amount = credits, Why = "honeypot", Item = l.Item, OrderId = o.Id, Group = HoneypotStart });
|
||||
return o;
|
||||
}
|
||||
|
||||
private static void Refund(Wallet w, BmOrder o)
|
||||
{
|
||||
w.Add(o.Asset, o.Qty);
|
||||
w.Taint += o.Taint; w.Basis += o.Basis;
|
||||
}
|
||||
|
||||
/// <summary>每晚推进订单:平台跑路、到期的订单(卖家跑路、被截获、死投被挖走)、转入可取状态。镇压期间到期顺延一天。</summary>
|
||||
public List<BmEvent> Night(int day, bool crackdown, Wallet w, Rng rng, int secRep = 0, Func<string, double> price = null) => Night(day, crackdown, _ => w, rng, secRep, price);
|
||||
|
||||
/// <summary>每晚(多钱包):退款回付款的钱包,出售回款进上架时付费的钱包。</summary>
|
||||
public List<BmEvent> Night(int day, bool crackdown, Func<string, Wallet> w, Rng rng, int secRep = 0, Func<string, double> price = null)
|
||||
{
|
||||
var ev = new List<BmEvent>();
|
||||
if (!Honeypot(day) && rng.Chance(HoneypotChance(secRep))) { HoneypotUntil = day + Tuning.BmHoneypotDays; HoneypotStart = day; if (!Forum.Contains("easy")) Forum.Add("easy"); }
|
||||
if (ClosedUntil == day) ev.Add(new BmEvent { Kind = "reopen" });
|
||||
if (!Closed(day) && (Orders.Any(o => o.State == OrderState.Pending) || Sales.Any(x => x.State == SaleState.Listed || x.State == SaleState.Sold)) && rng.Chance(RugChance))
|
||||
{
|
||||
foreach (var o in Orders.Where(o => o.State == OrderState.Pending))
|
||||
{
|
||||
o.State = OrderState.Lost; o.Why = "rug"; DropTraps(o);
|
||||
ev.Add(new BmEvent { Kind = "rug", Order = o, Amount = o.Price });
|
||||
}
|
||||
foreach (var sl in Sales.Where(x => x.State == SaleState.Listed || x.State == SaleState.Sold))
|
||||
{
|
||||
ev.Add(new BmEvent { Kind = "sale_rug", Sale = sl, Amount = sl.State == SaleState.Sold ? sl.Proceeds : sl.ListPrice });
|
||||
sl.State = SaleState.Lost; sl.Why = "rug";
|
||||
}
|
||||
ClosedUntil = day + Tuning.BmRugClosedDays;
|
||||
Offers.Clear(); Catalog.Clear(); Sellers.Clear();
|
||||
return ev;
|
||||
}
|
||||
foreach (var o in Orders.Where(x => x.State == OrderState.Pending).ToList())
|
||||
{
|
||||
if (day < o.DueDay) continue;
|
||||
if (crackdown) { o.DueDay = day + 1; continue; }
|
||||
if (o.SellerScam)
|
||||
{
|
||||
if (o.Mode == PayMode.Escrow) { Refund(w(o.Wallet), o); o.State = OrderState.Refunded; o.Why = "scam"; DropTraps(o); ev.Add(new BmEvent { Kind = "scam_refund", Order = o, Amount = o.Price }); }
|
||||
else { o.State = OrderState.Lost; o.Why = "scam"; DropTraps(o); ev.Add(new BmEvent { Kind = "scam_loss", Order = o, Amount = o.Price }); }
|
||||
continue;
|
||||
}
|
||||
double ic = Tuning.BmInterceptDoor + (crackdown ? Tuning.BmInterceptCrackdown : 0);
|
||||
if (rng.Chance(ic))
|
||||
{
|
||||
if (rng.Chance(Tuning.BmControlled)) { o.Controlled = true; o.State = OrderState.Ready; ev.Add(new BmEvent { Kind = "ready", Order = o }); continue; }
|
||||
o.State = OrderState.Lost; o.Why = "intercept"; DropTraps(o); ev.Add(new BmEvent { Kind = "intercept", Order = o, Amount = o.Price }); continue;
|
||||
}
|
||||
o.State = OrderState.Ready;
|
||||
ev.Add(new BmEvent { Kind = "ready", Order = o });
|
||||
}
|
||||
if (price != null) SalesNight(day, crackdown, w, price, rng, ev);
|
||||
// 卖家落网:近期成交过的卖家各有小概率被抓,他们留存的订单记录之后会连累买家
|
||||
foreach (var name in Orders.Where(x => x.State == OrderState.Done && day - x.DueDay <= 14).Select(x => x.Seller).Distinct().ToList())
|
||||
{
|
||||
if (!rng.Chance(Tuning.BmSellerBust)) continue;
|
||||
foreach (var o in Orders.Where(x => x.State == OrderState.Done && x.Seller == name && day - x.DueDay <= 14))
|
||||
Traps.Add(new BmTrap { Day = day + Tuning.BmTrapDelay, Amount = o.Price, Why = "seller", Item = o.Item, Group = -day });
|
||||
Forum.Add("busted:" + name);
|
||||
}
|
||||
// 同一晚到期的追查按来源(同一次蜜罐 / 落网)合成一次事件;记入货款的一部分,同一次累计有上限
|
||||
var due = Traps.Where(x => day >= x.Day).ToList();
|
||||
foreach (var g in due.GroupBy(x => new { x.Why, x.Group }))
|
||||
{
|
||||
Charged.TryGetValue(g.Key.Group, out double done);
|
||||
double amount = Math.Min(g.Sum(x => x.Amount) * Tuning.BmTrapShare, Tuning.BmTrapWindowCap - done);
|
||||
if (amount < 1) continue;
|
||||
Charged[g.Key.Group] = done + amount;
|
||||
ev.Add(new BmEvent { Kind = "trap", Amount = amount, Order = new BmOrder { Item = g.First().Item, Seller = g.Key.Why } });
|
||||
}
|
||||
Traps.RemoveAll(x => day >= x.Day);
|
||||
Orders.RemoveAll(o => o.State != OrderState.Pending && o.State != OrderState.Ready && day - o.DueDay > 14);
|
||||
return ev;
|
||||
}
|
||||
|
||||
/// <summary>受控交付:签收则当场记罪证(返回金额)并查封,不交货;拒签则损失货款,不留罪证。</summary>
|
||||
public double Sign(BmOrder o, bool accept)
|
||||
{
|
||||
o.State = OrderState.Lost;
|
||||
o.Why = accept ? "seized" : "refused";
|
||||
DropTraps(o);
|
||||
return accept ? o.Price : 0;
|
||||
}
|
||||
|
||||
public void Deliver(BmOrder o) { o.State = OrderState.Done; o.Why = "done"; }
|
||||
|
||||
public IEnumerable<BmOrder> Ready => Orders.Where(o => o.State == OrderState.Ready);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,183 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
|
||||
namespace Decentralized.Domain
|
||||
{
|
||||
public enum SaleState { Listed, Sold, Paid, Lost, Delisted }
|
||||
|
||||
/// <summary>玩家在黑市上架的一件货。货交给平台(从储藏区拿走),成交后货款托管几天再到钱包,可能带污点。</summary>
|
||||
public sealed class BmSale
|
||||
{
|
||||
public string Item;
|
||||
public string Model, FakeOf;
|
||||
public double Health;
|
||||
/// <summary>标价倍率与标价(信用点)。</summary>
|
||||
public double Mult;
|
||||
/// <summary>参考价:改价时按它重算标价。</summary>
|
||||
public long Ref;
|
||||
public int ListPrice;
|
||||
/// <summary>上架时付费的钱包地址:回款进这里。</summary>
|
||||
public string Wallet;
|
||||
public int ListedDay, PayDay;
|
||||
public SaleState State = SaleState.Listed;
|
||||
/// <summary>成交后扣掉抽成的货款(信用点)与其中带的污点。</summary>
|
||||
public int Proceeds;
|
||||
public double Taint;
|
||||
/// <summary>上架那件货的赃物热度(0–100):赃物的货款按"货款 × 热度%"带污点,不走随机。</summary>
|
||||
public double Heat;
|
||||
/// <summary>成交那一轮的收款币(空 = CRT,旧存档):货款到期后以这个币付给钱包。</summary>
|
||||
public string PayAsset;
|
||||
/// <summary>终态原因:fake(买家看穿假卡退货)/ rug / delist。</summary>
|
||||
public string Why;
|
||||
|
||||
/// <summary>聚合键:同一种商品(标识、型号、真伪、成色取整)算一组,同组倍率相同。</summary>
|
||||
public static string KeyOf(string item, string model, string fakeOf, double health) => item + "|" + model + "|" + fakeOf + "|" + Math.Round(health);
|
||||
public string Key => KeyOf(Item, Model, FakeOf, Health);
|
||||
}
|
||||
|
||||
public sealed partial class BlackMarket
|
||||
{
|
||||
public List<BmSale> Sales = new List<BmSale>();
|
||||
/// <summary>玩家作为卖家的好评(%):影响成交速度;卖假卡被看穿会下降,每笔成交回升一点。</summary>
|
||||
public int Rating = Tuning.BmRatingStart;
|
||||
|
||||
/// <summary>期望成交天数:倍率不高于 BmSellFastMult 取 BmSellDaysFast,BmSellDay1Mult 取 BmSellDays1,BmSellMax 取 BmSellDaysMax,之间插值(快档到一档线性,一档以上指数)。</summary>
|
||||
public static double ExpectedDays(double m)
|
||||
{
|
||||
if (m <= Tuning.BmSellFastMult) return Tuning.BmSellDaysFast;
|
||||
if (m < Tuning.BmSellDay1Mult) return Tuning.BmSellDaysFast + (m - Tuning.BmSellFastMult) / (Tuning.BmSellDay1Mult - Tuning.BmSellFastMult) * (Tuning.BmSellDays1 - Tuning.BmSellDaysFast);
|
||||
return Tuning.BmSellDays1 * Math.Pow(Tuning.BmSellDaysMax / Tuning.BmSellDays1, (m - Tuning.BmSellDay1Mult) / (Tuning.BmSellMax - Tuning.BmSellDay1Mult));
|
||||
}
|
||||
|
||||
private static double T(double m) => Math.Max(0, Math.Min(1, (m - Tuning.BmSellMin) / (Tuning.BmSellMax - Tuning.BmSellMin)));
|
||||
/// <summary>货款带污点的概率与(带的时候)污点占货款的比例:都随标价倍率上升。</summary>
|
||||
public static double TaintChance(double m) => Tuning.BmSaleTaintChanceMin + T(m) * (Tuning.BmSaleTaintChanceMax - Tuning.BmSaleTaintChanceMin);
|
||||
public static double TaintRatio(double m) => Tuning.BmSaleTaintRatioMin + T(m) * (Tuning.BmSaleTaintRatioMax - Tuning.BmSaleTaintRatioMin);
|
||||
|
||||
/// <summary>每晚成交的概率:1 / 期望天数,乘好评系数(好评 90 为 1,封顶 1.1),最多 1。</summary>
|
||||
public double SaleChance(double m) => Math.Min(1, 1 / ExpectedDays(m) * Math.Min(1.1, Rating / (double)Tuning.BmRatingStart));
|
||||
|
||||
/// <summary>近 7 天成交额推高的污点加成:出售量越大,货款越容易带污点、比例越高。</summary>
|
||||
public double VolumeTaint(int day)
|
||||
{
|
||||
double v = Sales.Where(x => (x.State == SaleState.Sold || x.State == SaleState.Paid) && day - (x.PayDay - Tuning.BmSaleHold) <= 7).Sum(x => (double)x.Proceeds);
|
||||
return Math.Min(Tuning.BmVolumeTaintMax, v / Tuning.BmVolumeRef * Tuning.BmVolumeTaintMax);
|
||||
}
|
||||
|
||||
/// <summary>收款币:愿意接受的币(存档),至少一种;默认只有 CRT。</summary>
|
||||
public List<string> SellAccepts = new List<string> { Assets.CRT };
|
||||
public static readonly string[] SellCoins = { Assets.PSC, Assets.CRT, Assets.CRA, Assets.Ponero };
|
||||
|
||||
public static double CoinWeight(string asset) =>
|
||||
asset == Assets.PSC ? Tuning.BmWeightPsc : asset == Assets.CRT ? Tuning.BmWeightCrt : asset == Assets.CRA ? Tuning.BmWeightCra : asset == Assets.Ponero ? Tuning.BmWeightPonero : 0;
|
||||
|
||||
public IEnumerable<string> AcceptedCoins => SellAccepts.Count == 0 ? new[] { Assets.CRT } : SellAccepts.Where(a => CoinWeight(a) > 0).Distinct().ToArray();
|
||||
|
||||
/// <summary>开关一种收款币;最后一种不能关掉。</summary>
|
||||
public bool ToggleCoin(string asset)
|
||||
{
|
||||
if (SellAccepts.Count == 0) SellAccepts.Add(Assets.CRT);
|
||||
if (SellAccepts.Contains(asset)) { if (SellAccepts.Count <= 1) return false; SellAccepts.Remove(asset); return true; }
|
||||
if (CoinWeight(asset) <= 0) return false;
|
||||
SellAccepts.Add(asset);
|
||||
return true;
|
||||
}
|
||||
|
||||
/// <summary>在架的件数(全部)、种数、某一组的件数与倍率(没有在架返回 null)。</summary>
|
||||
public int ActiveListings => Sales.Count(x => x.State == SaleState.Listed);
|
||||
public int ActiveKinds => Sales.Where(x => x.State == SaleState.Listed).Select(x => x.Key).Distinct().Count();
|
||||
public int ActiveOf(string key) => Sales.Count(x => x.State == SaleState.Listed && x.Key == key);
|
||||
public double? MultOf(string key) { var s = Sales.FirstOrDefault(x => x.State == SaleState.Listed && x.Key == key); return s == null ? (double?)null : s.Mult; }
|
||||
|
||||
/// <summary>某一组再上架 add 件、倍率 m 时的限制:null = 可以;stack = 超过每种上限;kinds = 超过种数上限;mult = 与已在架的同种货倍率不同。</summary>
|
||||
public string ListBlock(string key, double m, int add = 1)
|
||||
{
|
||||
int have = ActiveOf(key);
|
||||
if (have + add > Tuning.BmMaxStack) return "stack";
|
||||
if (have == 0 && ActiveKinds >= Tuning.BmMaxKinds) return "kinds";
|
||||
var cur = MultOf(key);
|
||||
if (cur != null && Math.Abs(cur.Value - m) > 1e-9) return "mult";
|
||||
return null;
|
||||
}
|
||||
|
||||
public static int ListPriceOf(long refValue, double m) => (int)Math.Max(1, Math.Round(refValue * m));
|
||||
public static int ListFee(int listPrice) => (int)Math.Ceiling(listPrice * Tuning.BmListFee);
|
||||
|
||||
/// <summary>上架:交付一件货,收上架费(付给 feeAsset 币,污点与成本按比例带走)。heat 是这件货的赃物热度(0–100)。倍率超出范围、平台关闭或余额不足返回 null。</summary>
|
||||
public BmSale List(string item, string model, string fakeOf, double health, long refValue, double m, Wallet w, string feeAsset, int day, Func<string, double> price, double heat = 0)
|
||||
{
|
||||
if (m < Tuning.BmSellMin - 1e-9 || m > Tuning.BmSellMax + 1e-9 || refValue <= 0 || Closed(day) || feeAsset == Assets.CRC || ListBlock(BmSale.KeyOf(item, model, fakeOf, health), m) != null) return null;
|
||||
int listPrice = ListPriceOf(refValue, m);
|
||||
double p = price(feeAsset);
|
||||
if (p <= 0) return null;
|
||||
double qty = ListFee(listPrice) / p;
|
||||
if (w.Avail(feeAsset) + 1e-9 < qty) return null;
|
||||
double total = w.Value(price);
|
||||
double share = total > 0 ? Math.Min(1, ListFee(listPrice) / total) : 0;
|
||||
w.Taint -= w.Taint * share; w.Basis -= w.Basis * share;
|
||||
w.Add(feeAsset, -qty);
|
||||
var s = new BmSale { Item = item, Model = model, FakeOf = fakeOf, Health = health, Ref = refValue, Mult = m, ListPrice = listPrice, ListedDay = day, Wallet = w.Address, Heat = Math.Max(0, Math.Min(100, heat)) };
|
||||
Sales.Add(s);
|
||||
return s;
|
||||
}
|
||||
|
||||
public void Delist(BmSale s) { s.State = SaleState.Delisted; s.Why = "delist"; }
|
||||
|
||||
/// <summary>未到账的货款(信用点):跑路时一并归零,也推高跑路概率。</summary>
|
||||
public double HeldSales => Sales.Where(x => x.State == SaleState.Sold).Sum(x => (double)x.Proceeds);
|
||||
|
||||
/// <summary>每晚推进出售:上架的货按概率成交(假卡可能被看穿退货),成交的货款托管到期后进钱包。镇压期间平台下线,不推进。</summary>
|
||||
private void SalesNight(int day, bool crackdown, Func<string, Wallet> wallet, Func<string, double> price, Rng rng, List<BmEvent> ev)
|
||||
{
|
||||
if (crackdown) return;
|
||||
foreach (var s in Sales.Where(x => x.State == SaleState.Listed && x.ListedDay < day).ToList())
|
||||
{
|
||||
// 每接受一种币算一轮成交:轮次顺序随机,任一轮命中即成交,货款用命中的币付
|
||||
string hit = null;
|
||||
double chance = SaleChance(s.Mult);
|
||||
foreach (var c in AcceptedCoins.OrderBy(_ => rng.NextDouble()).ToList())
|
||||
if (rng.Chance(Math.Min(1, chance * CoinWeight(c)))) { hit = c; break; }
|
||||
if (hit == null) continue;
|
||||
s.PayAsset = hit;
|
||||
if (s.FakeOf != null && rng.Chance(Tuning.BmFakeDetect))
|
||||
{
|
||||
s.State = SaleState.Delisted; s.Why = "fake";
|
||||
Rating = Math.Max(0, Rating - Tuning.BmRatingFakeLoss);
|
||||
ev.Add(new BmEvent { Kind = "sale_fake", Sale = s });
|
||||
continue;
|
||||
}
|
||||
s.State = SaleState.Sold;
|
||||
s.Proceeds = (int)Math.Round(s.ListPrice * (1 - Tuning.BmCommission));
|
||||
double vb = VolumeTaint(day);
|
||||
s.Taint = s.Heat > 0 ? s.Proceeds * s.Heat / 100
|
||||
: rng.Chance(Math.Min(1, TaintChance(s.Mult) + vb)) ? s.Proceeds * Math.Min(1, TaintRatio(s.Mult) + vb) : 0;
|
||||
s.PayDay = day + Tuning.BmSaleHold;
|
||||
Rating = Math.Min(100, Rating + 1);
|
||||
if (Honeypot(day)) Traps.Add(new BmTrap { Day = day + Tuning.BmTrapDelay, Amount = s.Proceeds, Why = "honeypot", Item = s.Item, Group = HoneypotStart });
|
||||
ev.Add(new BmEvent { Kind = "sale_sold", Sale = s, Amount = s.Proceeds });
|
||||
}
|
||||
foreach (var s in Sales.Where(x => x.State == SaleState.Sold && day >= x.PayDay).ToList())
|
||||
{
|
||||
string pa = s.PayAsset ?? Assets.CRT;
|
||||
double p = price(pa);
|
||||
if (p <= 0) continue;
|
||||
var w = wallet(s.Wallet);
|
||||
w.Add(pa, s.Proceeds / p);
|
||||
w.Taint += s.Taint;
|
||||
w.Basis += s.Proceeds;
|
||||
s.State = SaleState.Paid;
|
||||
ev.Add(new BmEvent { Kind = "sale_paid", Sale = s, Amount = s.Proceeds });
|
||||
}
|
||||
// 买家落网:近期到账的出售记录会连累卖家(玩家)
|
||||
var recent = Sales.Where(x => x.State == SaleState.Paid && day - x.PayDay <= 14).ToList();
|
||||
if (recent.Count > 0 && rng.Chance(Tuning.BmSellerBust))
|
||||
{
|
||||
foreach (var s in recent) Traps.Add(new BmTrap { Day = day + Tuning.BmTrapDelay, Amount = s.Proceeds, Why = "seller", Item = s.Item, Group = -day });
|
||||
Forum.Add("busted_buyer");
|
||||
}
|
||||
Sales.RemoveAll(x => (x.State == SaleState.Paid || x.State == SaleState.Delisted || x.State == SaleState.Lost) && day - Math.Max(x.ListedDay, x.PayDay) > 14);
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,86 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
|
||||
namespace Decentralized.Domain
|
||||
{
|
||||
/// <summary>一天一根蜡烛:开盘接前一天的收盘价、包括夜间变动和白天真实发生过的最高 / 最低、夜间结算前的收盘价;成交额分玩家和 NPC 大户(信用点)。</summary>
|
||||
public sealed class Candle
|
||||
{
|
||||
public int Day;
|
||||
public double O, H, L, C, VolPlayer, VolNpc;
|
||||
public bool Closed;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 日 K 历史(按币种)。开门时开一根,白天的价格变动(开门波动、插针、大户、玩家大单)更新高低和现价,夜间结算时收盘。
|
||||
/// 没有发生过的日内走势不编造:没有事件的日子高低就等于开收。
|
||||
/// </summary>
|
||||
public sealed class CandleBook
|
||||
{
|
||||
public const int Keep = 60;
|
||||
public Dictionary<string, List<Candle>> Series = new Dictionary<string, List<Candle>>();
|
||||
|
||||
public List<Candle> Of(string asset) => Series.TryGetValue(asset, out var s) ? s : new List<Candle>();
|
||||
|
||||
/// <summary>今天的蜡烛:没有就按现价开一根(读档时补上,开盘价就是读档时的价格)。</summary>
|
||||
public Candle Today(string asset, int day, double price)
|
||||
{
|
||||
if (!Series.TryGetValue(asset, out var s)) Series[asset] = s = new List<Candle>();
|
||||
var c = s.Count > 0 ? s[s.Count - 1] : null;
|
||||
if (c != null && c.Day == day) return c;
|
||||
c = new Candle { Day = day, O = price, H = price, L = price, C = price };
|
||||
s.Add(c);
|
||||
while (s.Count > Keep) s.RemoveAt(0);
|
||||
return c;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 开门:新开一根。币是全天候交易的,所以开盘价接昨天的收盘价,夜里的回归和开门波动都算进这根蜡烛(没有跳空);
|
||||
/// 没有昨天的(刚开始记录)就从现价开。
|
||||
/// </summary>
|
||||
public void Open(string asset, int day, double price)
|
||||
{
|
||||
var s = Of(asset);
|
||||
var prev = s.Count > 0 && s[s.Count - 1].Day < day ? s[s.Count - 1] : null;
|
||||
var c = Today(asset, day, price);
|
||||
if (c.Closed) return;
|
||||
double o = prev != null ? prev.C : price;
|
||||
c.O = o; c.H = Math.Max(o, price); c.L = Math.Min(o, price); c.C = price;
|
||||
}
|
||||
|
||||
/// <summary>白天的价格变动。</summary>
|
||||
public void Tick(string asset, int day, double price, double volume = 0, bool player = false)
|
||||
{
|
||||
var c = Today(asset, day, price);
|
||||
if (c.Closed) return;
|
||||
c.H = Math.Max(c.H, price); c.L = Math.Min(c.L, price); c.C = price;
|
||||
if (player) c.VolPlayer += Math.Abs(volume); else c.VolNpc += Math.Abs(volume);
|
||||
}
|
||||
|
||||
/// <summary>夜间结算:收盘。</summary>
|
||||
public void Close(string asset, int day, double price)
|
||||
{
|
||||
Tick(asset, day, price);
|
||||
Today(asset, day, price).Closed = true;
|
||||
}
|
||||
|
||||
/// <summary>NPC 当天的成交额(信用点):基础量随池深,波动越大成交越多。</summary>
|
||||
public static double NpcVolume(double depth, double share, double absMove, Rng rng) =>
|
||||
depth * share * (1 + Tuning.ChartVolMove * absMove) * rng.Range(0.6, 1.4);
|
||||
|
||||
/// <summary>收盘价的 n 日均线(不足 n 根时用已有的);每根蜡烛一个值。</summary>
|
||||
public static List<double> Ma(IList<Candle> s, int n)
|
||||
{
|
||||
var r = new List<double>();
|
||||
for (int i = 0; i < s.Count; i++)
|
||||
{
|
||||
int a = Math.Max(0, i - n + 1);
|
||||
double sum = 0;
|
||||
for (int j = a; j <= i; j++) sum += s[j].C;
|
||||
r.Add(sum / (i - a + 1));
|
||||
}
|
||||
return r;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,191 @@
|
||||
using System;
|
||||
using System.Linq;
|
||||
|
||||
namespace Decentralized.Domain
|
||||
{
|
||||
/// <summary>卖家的说法:每个标签一项。型号是文字,其余取值与 <see cref="CardLook"/> 一致;「供电与风扇」由说法里的型号决定档次。</summary>
|
||||
public struct Claim
|
||||
{
|
||||
public string Model;
|
||||
public int Fan, Fingers, Bracket, Print, Sticker, Serial;
|
||||
/// <summary>风扇数、供电口:0 表示由型号的档次决定(说法里写的型号该有的),否则是写明的值(风扇数 1 到 3;供电口 1 到 3,对应 0 到 2 加一)。</summary>
|
||||
public int CountSet, PinSet;
|
||||
|
||||
public int Tier => Hardware.Specs[Model].Tier;
|
||||
public int Count => CountSet != 0 ? CountSet : Hardware.FanCount[Tier];
|
||||
public int Pin => PinSet != 0 ? PinSet - 1 : Hardware.PinClass[Tier];
|
||||
|
||||
public int Get(int row) => row == CardLabels.RowCount ? Count : row == CardLabels.RowPin ? Pin : row == CardLabels.RowFan ? Fan : row == CardLabels.RowFingers ? Fingers
|
||||
: row == CardLabels.RowBracket ? Bracket : row == CardLabels.RowPrint ? Print : row == CardLabels.RowSerial ? Serial : Sticker;
|
||||
|
||||
public Claim With(int row, int value)
|
||||
{
|
||||
var c = this;
|
||||
if (row == CardLabels.RowFan) c.Fan = value; else if (row == CardLabels.RowFingers) c.Fingers = value;
|
||||
else if (row == CardLabels.RowBracket) c.Bracket = value; else if (row == CardLabels.RowPrint) c.Print = value;
|
||||
else if (row == CardLabels.RowSerial) c.Serial = value; else if (row == CardLabels.RowSeal) c.Sticker = value;
|
||||
else if (row == CardLabels.RowCount) c.CountSet = value; else if (row == CardLabels.RowPin) c.PinSet = value + 1;
|
||||
return c;
|
||||
}
|
||||
|
||||
public string Encode() => $"{Model}:{Fan}{Fingers}{Bracket}{Print}{Sticker}{Serial}{CountSet}{PinSet}";
|
||||
|
||||
public static Claim Decode(string s)
|
||||
{
|
||||
var p = (s ?? "").Split(':');
|
||||
if (p.Length != 2 || (p[1].Length != 6 && p[1].Length != 8) || !Hardware.Specs.ContainsKey(p[0])) return default;
|
||||
int D(int i) => Math.Max(0, Math.Min(2, p[1][i] - '0'));
|
||||
int E(int i) => p[1].Length > i ? Math.Max(0, Math.Min(3, p[1][i] - '0')) : 0;
|
||||
return new Claim { Model = p[0], Fan = D(0), Fingers = D(1), Bracket = D(2), Print = D(3), Sticker = D(4), Serial = D(5), CountSet = E(6), PinSet = E(7) };
|
||||
}
|
||||
|
||||
/// <summary>按真实情况写出的说法(没有隐瞒)。</summary>
|
||||
public static Claim Truth(Unit u)
|
||||
{
|
||||
var l = u.Appearance;
|
||||
return new Claim { Model = u.FakeOf ?? u.Model, Fan = l.Fan, Fingers = l.Fingers, Bracket = l.Bracket, Print = l.Print, Sticker = l.Sticker, Serial = l.Serial, CountSet = u.ObservedCount, PinSet = u.ObservedPin + 1 };
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 标签栏的数据:五个标签(型号真伪、风扇叶片、金手指、挡板、封条),每个标签有卖家的说法和真实情况;
|
||||
/// 供电与风扇、背面丝印、序列号三项是型号真伪的依据,只存状态,不单独成行。
|
||||
/// 一个标签被指出(拆穿)之后,说法改回真实情况;价格按「已指出的标签取真实情况,其余取说法」算,
|
||||
/// 所以卖家隐瞒的问题要玩家一项项指出来才能把价格拉回真实价值。指出型号有问题,型号自动改回真实型号。
|
||||
/// </summary>
|
||||
public static class CardLabels
|
||||
{
|
||||
public const int RowSpec = 1, RowCount = 2, RowFan = 4, RowFingers = 8, RowBracket = 16, RowPrint = 32, RowSerial = 64, RowSeal = 128, RowPin = 256, AllRows = 511;
|
||||
/// <summary>标签栏的顺序:风扇数、供电口、背面丝印、序列号(真伪依据),型号,叶片、金手指、挡板、封条(成色)。</summary>
|
||||
public static readonly int[] Rows = { RowSpec, RowCount, RowPin, RowPrint, RowSerial, RowFan, RowFingers, RowBracket, RowSeal };
|
||||
/// <summary>第一行是型号(唯一的“指出型号”按钮),接着四行是真伪依据(风扇数、供电口、背面丝印、序列号,只读,四项全部符合标称型号才是正品),之后四行是成色。</summary>
|
||||
public const int AuthRows = 5;
|
||||
public static bool IsAuth(int row) => row == RowCount || row == RowPin || row == RowPrint || row == RowSerial;
|
||||
|
||||
/// <summary>各标签各取值对价格的影响(百分比,相加):风扇叶片积灰 −4%、缺角 −12%;金手指发暗 −4%、氧化 −12%;挡板划痕 −2%;封条缺失 −6%。
|
||||
/// 型号、供电与风扇、丝印、序列号本身不扣价,它们决定的是这块卡是什么芯片。</summary>
|
||||
public static double Pct(int row, int value)
|
||||
{
|
||||
switch (row)
|
||||
{
|
||||
case RowFan: return value == 1 ? -Tuning.CardFanDust * 100 : value == 2 ? -Tuning.CardFanChipped * 100 : 0;
|
||||
case RowFingers: return value == 1 ? -Tuning.CardFingersDark * 100 : value == 2 ? -Tuning.CardFingersOxidized * 100 : 0;
|
||||
case RowBracket: return value == 1 ? -Tuning.CardBracketScratch * 100 : 0;
|
||||
case RowSeal: return value == 2 ? -Tuning.CardSealMissing * 100 : 0;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
/// <summary>这一行是不是假货的证据:说法与真实情况不同,并且真实情况本身不该出现在真卡上。</summary>
|
||||
public static bool IsEvidence(int row, Claim claim, Claim real)
|
||||
{
|
||||
switch (row)
|
||||
{
|
||||
case RowCount: return claim.Count != real.Count;
|
||||
case RowPin: return claim.Pin != real.Pin;
|
||||
case RowPrint: return real.Print != 0 && claim.Print != real.Print;
|
||||
case RowSerial: return real.Serial != 0 && claim.Serial != real.Serial;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 价值:claim 为空表示没有人说过什么,一律按真实情况;exposed 里的位表示已指出的标签(取真实情况)。
|
||||
/// 型号取「说法里的型号」,型号标签被拆穿之后取真实芯片。价值 = 型号定价 ×(0.25 + 0.75 × 健康度)×(1 + 各标签折扣之和)。
|
||||
/// </summary>
|
||||
public static long Value(Unit u, Claim? claim, int exposed)
|
||||
{
|
||||
var real = Claim.Truth(u);
|
||||
Claim believed = claim == null ? real : claim.Value;
|
||||
double sum = 0;
|
||||
foreach (int r in new[] { RowFan, RowFingers, RowBracket, RowSeal })
|
||||
{
|
||||
int v = claim == null || (exposed & r) != 0 ? real.Get(r) : believed.Get(r);
|
||||
sum += Pct(r, v);
|
||||
}
|
||||
string model = claim == null || (exposed & RowSpec) != 0 ? real.Model : believed.Model;
|
||||
double value = CardValue.Of(model, u.Health) * Math.Max(0, 1 + sum / 100.0);
|
||||
return Math.Max(1, (long)Math.Round(value));
|
||||
}
|
||||
|
||||
/// <summary>指出一个标签:返回 0 没问题(说法属实)、1 隐瞒了对价格不利的情况、2 拆穿了假货(型号一并改回真实型号)。</summary>
|
||||
public static int Point(Unit u, Claim claim, int row, ref int exposed)
|
||||
{
|
||||
var real = Claim.Truth(u);
|
||||
bool wasExposed = (exposed & row) != 0;
|
||||
exposed |= row;
|
||||
if (row == RowSpec) return claim.Model != real.Model ? 2 : 0;
|
||||
if (IsEvidence(row, claim, real))
|
||||
{
|
||||
exposed |= RowSpec | RowCount | RowPin | RowPrint | RowSerial;
|
||||
return 2;
|
||||
}
|
||||
if (wasExposed) return 0;
|
||||
return claim.Get(row) != real.Get(row) ? 1 : 0;
|
||||
}
|
||||
|
||||
/// <summary>说法里隐瞒了什么:说法比真实情况价值高的标签,型号不符,以及假货的证据。</summary>
|
||||
public static int Lies(Unit u, Claim claim, int exposed)
|
||||
{
|
||||
var real = Claim.Truth(u);
|
||||
int lies = 0;
|
||||
foreach (int r in Rows)
|
||||
{
|
||||
if ((exposed & r) != 0) continue;
|
||||
if (r == RowSpec) { if (claim.Model != real.Model) lies |= r; }
|
||||
else if (IsAuth(r)) { if (claim.Get(r) != real.Get(r)) lies |= r; }
|
||||
else if (claim.Get(r) != real.Get(r) && Pct(r, claim.Get(r)) > Pct(r, real.Get(r))) lies |= r;
|
||||
}
|
||||
return lies;
|
||||
}
|
||||
|
||||
/// <summary>卖家怎么说:老实人如实说;中间商每项有七成概率说成没问题;骗子全部说成没问题。假卡的型号一律说成标称型号。</summary>
|
||||
public static Claim DealerClaim(Unit u, DealerKind kind, Rng rng)
|
||||
{
|
||||
var c = Claim.Truth(u);
|
||||
if (kind == DealerKind.Honest) return c;
|
||||
c.Model = u.Model;
|
||||
double hide = kind == DealerKind.Scammer ? 1.0 : Tuning.UsedMiddlemanHide;
|
||||
c.CountSet = 0; c.PinSet = 0;
|
||||
foreach (int r in new[] { RowFan, RowFingers, RowBracket, RowPrint, RowSerial, RowSeal })
|
||||
if (rng.Chance(hide)) c = c.With(r, 0);
|
||||
return c;
|
||||
}
|
||||
|
||||
// ---------- 序列号 ----------
|
||||
|
||||
/// <summary>各牌子的序列号前缀与合法工厂码。序列号格式:前缀 + 档次码(1 到 4)+ "-" + 工厂码(两位)+ "-" + 四位流水。</summary>
|
||||
public static string BrandCode(string brand) => brand == Hardware.Probidia ? "PB" : "MD";
|
||||
public static readonly int[] ProbidiaFactories = { 11, 12, 21, 34, 47 }, PmdFactories = { 13, 22, 35, 41, 58 };
|
||||
public static int[] Factories(string brand) => brand == Hardware.Probidia ? ProbidiaFactories : PmdFactories;
|
||||
|
||||
private static uint Mix(uint seed, int salt)
|
||||
{
|
||||
uint x = seed * 2654435761u + (uint)salt * 40503u + 777u;
|
||||
x ^= x >> 15; x *= 2246822519u; x ^= x >> 13; x *= 3266489917u; x ^= x >> 16;
|
||||
return x;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 卡上贴纸的序列号。合规:前缀(牌子)+ 标称型号的档次码 + 合法工厂码 + 四位流水。
|
||||
/// 不合规(贴纸是后补的):工厂码不在合法范围,或流水只有三位。档次码不符:贴的是原芯片的序列号,档次码是真实芯片的档次。
|
||||
/// </summary>
|
||||
public static string SerialText(Unit u)
|
||||
{
|
||||
var label = Hardware.Specs[u.Model];
|
||||
var chip = Hardware.Specs[u.FakeOf ?? u.Model];
|
||||
uint seed = u.Look.Seed == 0 ? 12345u : u.Look.Seed;
|
||||
int kind = u.Appearance.Serial;
|
||||
int[] ok = Factories(label.Brand);
|
||||
int tier = (kind == 2 ? chip.Tier : label.Tier) + 1;
|
||||
int factory = ok[(int)(Mix(seed, 1) % (uint)ok.Length)];
|
||||
int number = 1000 + (int)(Mix(seed, 2) % 9000);
|
||||
if (kind == 1)
|
||||
{
|
||||
if (Mix(seed, 3) % 2 == 0) { int[] bad = { 0, 9, 66, 77, 88, 99 }; factory = bad[(int)(Mix(seed, 4) % (uint)bad.Length)]; }
|
||||
else number = 100 + (int)(Mix(seed, 5) % 900);
|
||||
}
|
||||
return $"{BrandCode(label.Brand)}{tier}-{factory:00}-{number}";
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -13,54 +13,113 @@ namespace Decentralized.Domain
|
||||
public int Fan;
|
||||
/// <summary>金手指:0 光亮,1 发暗,2 氧化发绿(老化)。</summary>
|
||||
public int Fingers;
|
||||
/// <summary>挡板:0 完好,1 划痕(老化),2 接口数量不对(假卡)。</summary>
|
||||
/// <summary>挡板:0 完好,1 划痕(老化)。</summary>
|
||||
public int Bracket;
|
||||
/// <summary>背面丝印:0 与标称型号一致,1 印的是真实芯片的型号(假卡),2 重新印过、字歪(假卡)。</summary>
|
||||
public int Print;
|
||||
/// <summary>背面贴纸与封条:0 印刷序列号、封条完好,1 手写序列号(假卡),2 封条缺失(旧卡或翻新卡)。</summary>
|
||||
/// <summary>封条:0 完好,2 缺失(开过封的旧卡或翻新卡)。</summary>
|
||||
public int Sticker;
|
||||
/// <summary>序列号:0 合规(格式对、工厂码在合法范围、档次码与型号一致),1 不合规(工厂码不在合法范围或位数不对,贴纸是后补的),
|
||||
/// 2 档次码与标称型号不符(贴的是原芯片的序列号)。后两种只出现在假卡上。</summary>
|
||||
public int Serial;
|
||||
|
||||
/// <summary>风扇数对不上标称型号(实物是真实芯片的风扇数):0 对得上,1 对不上。只出现在假卡上。</summary>
|
||||
public int CountBad;
|
||||
/// <summary>供电口对不上标称型号(实物是真实芯片的供电口):0 对得上,1 对不上。只出现在假卡上。</summary>
|
||||
public int PinBad;
|
||||
|
||||
public const int Variants = 3;
|
||||
|
||||
/// <summary>每张卡自己的随机种子:老化类维度(风扇、金手指、挡板划痕)由它和当前健康度决定,每晚损耗后重新算,
|
||||
/// 所以越旧的卡看着越旧。为 0 时表示外观是写死的(测试用)。</summary>
|
||||
public uint Seed;
|
||||
|
||||
private static double U(uint seed, int salt)
|
||||
{
|
||||
uint x = seed * 2654435761u + (uint)salt * 40503u + 12345u;
|
||||
x ^= x >> 15; x *= 2246822519u; x ^= x >> 13; x *= 3266489917u; x ^= x >> 16;
|
||||
return (x >> 8) * (1.0 / (1 << 24));
|
||||
}
|
||||
|
||||
/// <summary>按当前健康度重新算出的外观:磨损度 = 1 − 健康度 / 100,再加上这张卡自己的偏差(±0.15)。
|
||||
/// 风扇磨损 ≥ 0.25 积灰、≥ 0.55 缺角;金手指 ≥ 0.30 发暗、≥ 0.60 氧化;挡板磨损 ≥ 0.45 出划痕(接口数不对是假卡的固定特征,不变)。</summary>
|
||||
public CardLook Appearance(double health)
|
||||
{
|
||||
if (Seed == 0) return this;
|
||||
double worn = 1 - Math.Max(0, Math.Min(100, health)) / 100.0;
|
||||
var l = this;
|
||||
double fan = worn + (U(Seed, 1) - 0.5) * 0.3, fin = worn + (U(Seed, 2) - 0.5) * 0.3, brk = worn + (U(Seed, 3) - 0.5) * 0.3;
|
||||
l.Fan = fan >= 0.55 ? 2 : fan >= 0.25 ? 1 : 0;
|
||||
l.Fingers = fin >= 0.60 ? 2 : fin >= 0.30 ? 1 : 0;
|
||||
l.Bracket = brk >= 0.45 ? 1 : 0;
|
||||
return l;
|
||||
}
|
||||
|
||||
private static readonly double[] FanHash = { 1.00, 0.97, 0.92 }, FingerHash = { 1.00, 0.98, 0.94 };
|
||||
|
||||
/// <summary>算力倍数:风扇积灰 ×0.97、缺角 ×0.92(降频);金手指发暗 ×0.98、氧化 ×0.94(接触不良掉速)。</summary>
|
||||
public double HashFactor => FanHash[Fan] * FingerHash[Fingers];
|
||||
|
||||
/// <summary>六位数字,存在物品标签上:风扇、金手指、挡板、丝印、封条、序列号。</summary>
|
||||
public string Encode() => $"{Fan}{Fingers}{Bracket}{Print}{Sticker}{Serial}{CountBad}{PinBad}";
|
||||
|
||||
/// <summary>
|
||||
/// 旧版存档的外观只有 5 或 6 位(没有风扇数、供电口两位):旧规则里假卡的风扇数和供电口只要档次不同就一定对不上。
|
||||
/// 这里按旧规则补上,旧存档里的假卡仍然露出同样的破绽。新格式(8 位)不动。
|
||||
/// </summary>
|
||||
public static CardLook Legacy(string encoded, CardLook look, string label, string chip)
|
||||
{
|
||||
if (encoded == null || encoded.Length >= 8 || string.IsNullOrEmpty(chip) || chip == label) return look;
|
||||
var l = Hardware.Specs[label]; var c = Hardware.Specs[chip];
|
||||
look.CountBad = Hardware.FanCount[l.Tier] != Hardware.FanCount[c.Tier] ? 1 : 0;
|
||||
look.PinBad = Hardware.PinClass[l.Tier] != Hardware.PinClass[c.Tier] ? 1 : 0;
|
||||
return look;
|
||||
}
|
||||
|
||||
public static CardLook Decode(string s)
|
||||
{
|
||||
if (s == null || s.Length < 5 || s.Length > 8) return default;
|
||||
int D(int i) => Math.Max(0, Math.Min(Variants - 1, s[i] - '0'));
|
||||
int B(int i) => s.Length > i && s[i] == '1' ? 1 : 0;
|
||||
return new CardLook { Fan = D(0), Fingers = D(1), Bracket = D(2), Print = D(3), Sticker = D(4), Serial = s.Length > 5 ? D(5) : 0, CountBad = B(6), PinBad = B(7) };
|
||||
}
|
||||
|
||||
// 外观维度对应卡的真实状态:损耗、暴毙概率随之变化,价值走标签(见 CardLabels)
|
||||
private static readonly double[] FanWear = { 1.00, 1.10, 1.30 }, FanDeath = { 1.00, 1.00, 1.20 };
|
||||
private static readonly double[] FingerDeath = { 1.00, 1.10, 1.30 };
|
||||
|
||||
/// <summary>每晚损耗倍数:风扇积灰散热差 ×1.1,缺角 ×1.3。</summary>
|
||||
public double WearFactor => FanWear[Fan];
|
||||
|
||||
/// <summary>暴毙概率倍数:风扇缺角 ×1.2;金手指发暗 ×1.1、氧化 ×1.3(接触不良)。</summary>
|
||||
public double DeathFactor => FanDeath[Fan] * FingerDeath[Fingers];
|
||||
|
||||
/// <summary>只在假卡上出现的取值:玩家一旦看到,就能肯定是假的。</summary>
|
||||
public bool HasFakeSign => Bracket == 2 || Print != 0 || Sticker == 1;
|
||||
public bool HasFakeSign => Print != 0 || Serial != 0 || CountBad != 0 || PinBad != 0;
|
||||
|
||||
/// <summary>
|
||||
/// 生成外观。真卡:老化维度按健康度出现,封条缺失在二手卡上很常见,不会出现破绽类取值。
|
||||
/// 假卡:在三类破绽(接口数、丝印、手写序列号)里随机挑 1–3 处,再叠加老化与封条缺失。
|
||||
/// </summary>
|
||||
public static CardLook Generate(Rng rng, double health, bool fake)
|
||||
public static CardLook Generate(Rng rng, double health, bool fake, int labelTier = 3, int chipTier = 0)
|
||||
{
|
||||
double worn = 1 - Math.Max(0, Math.Min(100, health)) / 100.0;
|
||||
var look = new CardLook
|
||||
var look = new CardLook { Seed = rng.NextUInt() | 1, Sticker = rng.Chance(fake ? 0.35 : 0.15 + 0.30 * (1 - Math.Max(0, Math.Min(100, health)) / 100.0)) ? 2 : 0 };
|
||||
if (fake)
|
||||
{
|
||||
Fan = Pick(rng, 0.10 + 0.55 * worn, 0.35 * worn),
|
||||
Fingers = Pick(rng, 0.08 + 0.55 * worn, 0.40 * worn),
|
||||
Bracket = rng.Chance(0.10 + 0.50 * worn) ? 1 : 0,
|
||||
Sticker = rng.Chance(fake ? 0.35 : 0.15 + 0.30 * worn) ? 2 : 0,
|
||||
};
|
||||
if (!fake) return look;
|
||||
int signs = rng.Chance(0.55) ? 1 : rng.Chance(0.6) ? 2 : 3;
|
||||
var order = new[] { 0, 1, 2 };
|
||||
for (int i = order.Length - 1; i > 0; i--)
|
||||
{
|
||||
int j = rng.Range(0, i);
|
||||
(order[i], order[j]) = (order[j], order[i]);
|
||||
}
|
||||
for (int k = 0; k < signs; k++)
|
||||
{
|
||||
switch (order[k])
|
||||
// 四项真伪依据(风扇数、供电口、背面丝印、序列号)各自独立地露出破绽,至少一项;平均每张假卡约 1.5 项
|
||||
bool countCan = Hardware.FanCount[chipTier] != Hardware.FanCount[labelTier], pinCan = Hardware.PinClass[chipTier] != Hardware.PinClass[labelTier];
|
||||
double p = Tuning.FakeSignChance;
|
||||
for (int tries = 0; tries < 30 && !look.HasFakeSign; tries++)
|
||||
{
|
||||
case 0: look.Bracket = 2; break;
|
||||
case 1: look.Print = rng.Chance(0.6) ? 1 : 2; break;
|
||||
default: look.Sticker = 1; break;
|
||||
look.CountBad = countCan && rng.Chance(p) ? 1 : 0;
|
||||
look.PinBad = pinCan && rng.Chance(p) ? 1 : 0;
|
||||
look.Print = rng.Chance(p) ? (rng.Chance(0.6) ? 1 : 2) : 0;
|
||||
look.Serial = rng.Chance(p) ? (rng.Chance(0.55) ? 2 : 1) : 0;
|
||||
}
|
||||
if (!look.HasFakeSign) look.Serial = 1;
|
||||
}
|
||||
return look;
|
||||
return look.Appearance(health);
|
||||
}
|
||||
|
||||
/// <summary>p1 的概率取 1,再以 p2 的概率升到 2。</summary>
|
||||
private static int Pick(Rng rng, double p1, double p2) => rng.Chance(p1) ? (rng.Chance(p2 / Math.Max(p1, 1e-9)) ? 2 : 1) : 0;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
@@ -73,14 +132,11 @@ namespace Decentralized.Domain
|
||||
public static long Of(string model, double health)
|
||||
{
|
||||
var spec = Hardware.Specs[model];
|
||||
double f = 0.25 + 0.75 * Math.Max(0, Math.Min(100, health)) / 100.0;
|
||||
double f = Tuning.CardValueFloor + (1 - Tuning.CardValueFloor) * Math.Max(0, Math.Min(100, health)) / 100.0;
|
||||
return Math.Max(1, (long)Math.Round(spec.Price * f));
|
||||
}
|
||||
|
||||
/// <summary>真实价值(芯片型号 + 健康度)。</summary>
|
||||
public static long True(Unit u) => Of(u.FakeOf ?? u.Model, u.Health);
|
||||
|
||||
/// <summary>标称价:贩子报的价,按标称型号算;二手卡也折旧,但只按贩子"自称"的健康度。</summary>
|
||||
public static long Quoted(Unit u, double claimedHealth) => Of(u.Model, claimedHealth);
|
||||
/// <summary>真实价值:全部标签都按真实情况算。</summary>
|
||||
public static long True(Unit u) => CardLabels.Value(u, null, 0);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,71 @@
|
||||
namespace Decentralized.Domain
|
||||
{
|
||||
/// <summary>
|
||||
/// 链上地址:"0x" + 6 位随机十六进制 + 2 位校验位。手输地址时输错一位,校验位几乎总能发现(约 1/256 恰好也合法,币就转进了没人用的地址)。
|
||||
/// </summary>
|
||||
public static class ChainAddress
|
||||
{
|
||||
public const int BodyLength = 6, CheckLength = 2, Length = 2 + BodyLength + CheckLength;
|
||||
|
||||
public static string Make(uint r)
|
||||
{
|
||||
string body = (r & 0xFFFFFF).ToString("x6");
|
||||
return "0x" + body + Check(body);
|
||||
}
|
||||
|
||||
/// <summary>校验位:地址主体的 FNV-1a 散列取高 8 位(低位对单字符改动是一一对应的,永远不会碰巧合法)。</summary>
|
||||
public static string Check(string body)
|
||||
{
|
||||
uint h = 2166136261;
|
||||
foreach (char c in body) { h ^= c; h *= 16777619; }
|
||||
return (h >> 24).ToString("x2");
|
||||
}
|
||||
|
||||
public static string Normalize(string s) => (s ?? "").Trim().ToLowerInvariant();
|
||||
|
||||
/// <summary>格式对(0x 开头、十六进制、长度对)。</summary>
|
||||
public static bool WellFormed(string s)
|
||||
{
|
||||
s = Normalize(s);
|
||||
if (s.Length != Length || !s.StartsWith("0x")) return false;
|
||||
for (int i = 2; i < s.Length; i++)
|
||||
if (!(s[i] >= '0' && s[i] <= '9' || s[i] >= 'a' && s[i] <= 'f')) return false;
|
||||
return true;
|
||||
}
|
||||
|
||||
/// <summary>格式对且校验位对得上。</summary>
|
||||
public static bool Valid(string s)
|
||||
{
|
||||
s = Normalize(s);
|
||||
return WellFormed(s) && Check(s.Substring(2, BodyLength)) == s.Substring(2 + BodyLength);
|
||||
}
|
||||
|
||||
public static bool Same(string a, string b) => Normalize(a) == Normalize(b);
|
||||
|
||||
/// <summary>缩写(钱包列表里的样子):0x + 主体前 3 位 + … + 校验位,例如 0x4b9…17。</summary>
|
||||
public static string Short(string a)
|
||||
{
|
||||
a = Normalize(a);
|
||||
return WellFormed(a) ? a.Substring(0, 5) + "…" + a.Substring(2 + BodyLength) : a;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 相似地址(地址投毒、剪贴板木马用):主体前 3 位和校验位都和原地址一样,缩写看起来完全相同,中间几位不同;本身是合法地址,
|
||||
/// 币转过去就进了骗子手里。找不到校验位相同的就只保留前 3 位。
|
||||
/// </summary>
|
||||
public static string Lookalike(string a, Rng rng)
|
||||
{
|
||||
a = Normalize(a);
|
||||
if (!Valid(a)) return Make(rng.NextUInt());
|
||||
string prefix = a.Substring(2, 3), check = a.Substring(2 + BodyLength), body0 = a.Substring(2, BodyLength);
|
||||
for (int i = 0; i < 20000; i++)
|
||||
{
|
||||
string body = prefix + (rng.NextUInt() & 0xFFF).ToString("x3");
|
||||
if (body != body0 && Check(body) == check) return "0x" + body + check;
|
||||
}
|
||||
string fallback;
|
||||
do fallback = prefix + (rng.NextUInt() & 0xFFF).ToString("x3"); while (fallback == body0);
|
||||
return "0x" + fallback + Check(fallback);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,47 @@
|
||||
using System;
|
||||
|
||||
namespace Decentralized.Domain
|
||||
{
|
||||
/// <summary>
|
||||
/// 顾客用币付款:成交的信用点在店里扣回,按当前币价换成币进热钱包。
|
||||
/// 收赃物的款项不再记销赃,改为币带污点:货值 × 赃物热度%。
|
||||
/// </summary>
|
||||
public static class CoinPayment
|
||||
{
|
||||
/// <summary>各派系用什么币付款(其余派系不用币)。</summary>
|
||||
public static string AssetFor(string faction)
|
||||
{
|
||||
switch (faction)
|
||||
{
|
||||
case "FACTION_UPPER_LEVEL": return Assets.CRC;
|
||||
case "FACTION_BLACK_MARKET": return Assets.CRT;
|
||||
case "FACTION_REVOLUTION": return Assets.CRA;
|
||||
case "FACTION_LOWER_LEVEL": return Assets.PSC;
|
||||
default: return null;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>一位顾客用币付款的概率。</summary>
|
||||
public static double Chance(string asset)
|
||||
{
|
||||
switch (asset)
|
||||
{
|
||||
case Assets.CRC: return Tuning.CoinPayCrc;
|
||||
case Assets.CRT: return Tuning.CoinPayCrt;
|
||||
case Assets.CRA: return Tuning.CoinPayCra;
|
||||
default: return Tuning.CoinPayPsc;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>收款:返回收到的币数。heatPct 是物品的赃物热度(0–100)。多付的溢价是顾客给的额外收入,不带污点。</summary>
|
||||
public static double Receive(Wallet w, string asset, double credits, double price, double heatPct)
|
||||
{
|
||||
if (credits <= 0 || price <= 0) return 0;
|
||||
double qty = credits * (1 + Tuning.CoinPayPremium) / price; // 溢价只加在币数上,污点与成本仍按货值算
|
||||
w.Add(asset, qty);
|
||||
w.Taint += credits * Math.Max(0, Math.Min(100, heatPct)) / 100.0;
|
||||
w.Basis += credits;
|
||||
return qty;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -9,12 +9,12 @@ namespace Decentralized.Domain
|
||||
{
|
||||
public const string Rig = "RIG";
|
||||
|
||||
public static readonly string[] Basic = { "RZX50", "RZX60", "RZ470", "RZ580" };
|
||||
public static readonly string[] Advanced = { "RZX70", "RZX80Ti", "RZ6800" };
|
||||
public static readonly string[] Flagship = { "RZX90", "RZ7900" };
|
||||
public static readonly string[] Basic = { "RTX60", "RX70" };
|
||||
public static readonly string[] Advanced = { "RTX70", "RX80", "RTX80", "RX800" };
|
||||
public static readonly string[] Flagship = { "RTX90", "RX900" };
|
||||
|
||||
public const int AdvancedFromDay = 10, FlagshipFromDay = 30, SpecialFlagshipFromDay = 20;
|
||||
public const double RigRestockChance = 0.30, AdvancedChance = 0.60, AdvancedSecondChance = 0.30, FlagshipChance = 0.25;
|
||||
public const int AdvancedFromDay = Tuning.DealerAdvancedFromDay, FlagshipFromDay = Tuning.DealerFlagshipFromDay, SpecialFlagshipFromDay = Tuning.DealerSpecialFlagshipFromDay;
|
||||
public const double RigRestockChance = Tuning.DealerRigRestock, AdvancedChance = Tuning.DealerAdvanced, AdvancedSecondChance = Tuning.DealerAdvancedSecond, FlagshipChance = Tuning.DealerFlagship;
|
||||
|
||||
public static List<string> Stock(int day, bool ownsRig, bool specialStock, Rng rng)
|
||||
{
|
||||
|
||||
@@ -24,6 +24,9 @@ namespace Decentralized.Domain
|
||||
/// </summary>
|
||||
public sealed class Exchange
|
||||
{
|
||||
/// <summary>Poinbase 上架的币:只有这些能充值、能在现货交易。黑市的 CRT、革命军的 CRA 合规交易所不收。</summary>
|
||||
public static readonly string[] Listed = { Assets.PSC, Assets.CRC, Assets.SPARK };
|
||||
|
||||
/// <summary>最近的出金记录:(天, 金额)。</summary>
|
||||
public List<KeyValuePair<int, double>> History = new List<KeyValuePair<int, double>>();
|
||||
|
||||
@@ -33,9 +36,9 @@ namespace Decentralized.Domain
|
||||
double ratio = taint / amount;
|
||||
double big = Tuning.AmlBigRents * rent, cum = Tuning.AmlCumRents * rent;
|
||||
double p = 0;
|
||||
if (ratio >= Tuning.AmlTaintRatio) p += ratio * 1.5;
|
||||
p += Math.Max(0, (amount - big) / big) * 0.2;
|
||||
p += Math.Max(0, (recentTotal + amount - cum) / cum) * 0.2;
|
||||
if (ratio >= Tuning.AmlTaintRatio) p += ratio * Tuning.AmlTaintMult;
|
||||
p += Math.Max(0, (amount - big) / big) * Tuning.AmlExcessWeight;
|
||||
p += Math.Max(0, (recentTotal + amount - cum) / cum) * Tuning.AmlExcessWeight;
|
||||
if (fromMixerOrFlagged) p += Tuning.AmlMixerBonus;
|
||||
return Math.Min(Tuning.AmlMaxChance, p);
|
||||
}
|
||||
@@ -55,7 +58,7 @@ namespace Decentralized.Domain
|
||||
History.RemoveAll(h => h.Key <= day - Tuning.AmlWindowDays);
|
||||
double recent = History.Sum(h => h.Value);
|
||||
double value = amount * price(Assets.CRC);
|
||||
r.HitChance = HitChance(value, taint, recent, rent, fromMixer || wallet.Flagged);
|
||||
r.HitChance = Math.Min(1, HitChance(value, taint, recent, rent, fromMixer || wallet.Flagged) * StoryMods.Current.Aml(day));
|
||||
wallet.Add(Assets.CRC, -amount);
|
||||
wallet.Taint -= taint;
|
||||
wallet.Basis -= basis;
|
||||
|
||||
@@ -0,0 +1,55 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
|
||||
namespace Decentralized.Domain
|
||||
{
|
||||
/// <summary>一笔黑币报价:卖家手里的币、按现价的市值和他要的现金。Sting 是钓鱼执法(收下就记罪证,币不会到)。</summary>
|
||||
public sealed class HotOffer
|
||||
{
|
||||
public string Asset;
|
||||
public double Qty, Value;
|
||||
public int Cash;
|
||||
public bool Sting;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 收黑币:游戏里出了事,手里有来路不明的币的人上门,折价换现金。
|
||||
/// 帮派火并、镇压期间黑市的人出手 CRT;革命军袭击上层、下层动荡期间有人出手抢来的 PSC;黑市声望够了以后偶尔有人出手勒索得来的 Ponero。
|
||||
/// PSC、CRT 链上可追,收下的币按市值全额带污点;Ponero 不可追、不带污点,折扣也小,出口只有 Ponero 兑换处。
|
||||
/// </summary>
|
||||
public static class HotCoins
|
||||
{
|
||||
/// <summary>今天哪种黑币可能有人上门(按游戏当前的事件),没有返回 null。poneroOpen:Ponero 兑换处已开放。</summary>
|
||||
public static string Pick(ICollection<MarketEvent> active, bool poneroOpen, Rng rng)
|
||||
{
|
||||
var c = new List<string>();
|
||||
if (active.Contains(MarketEvent.GangWar) || active.Contains(MarketEvent.Crackdown)) c.Add(Assets.CRT);
|
||||
if (active.Contains(MarketEvent.RevRaidUpper) || active.Contains(MarketEvent.LowerUnrest)) c.Add(Assets.PSC);
|
||||
if (c.Count > 0 && rng.Chance(Tuning.HotEventChance)) return c[rng.Range(0, c.Count - 1)];
|
||||
if (poneroOpen && rng.Chance(Tuning.HotPoneroChance)) return Assets.Ponero;
|
||||
return null;
|
||||
}
|
||||
|
||||
/// <summary>开价:市值 = 房租 × 区间,现金要价 = 市值 × 折扣(Ponero 折扣小)。crackdown:镇压期间钓鱼执法更多。</summary>
|
||||
public static HotOffer Make(string asset, double coinPrice, double rent, bool crackdown, Rng rng)
|
||||
{
|
||||
if (coinPrice <= 0 || rent <= 0) return null;
|
||||
double value = rent * rng.Range(Tuning.HotValueMinRents, Tuning.HotValueMaxRents);
|
||||
bool ponero = asset == Assets.Ponero;
|
||||
double cut = ponero ? rng.Range(Tuning.HotPoneroCutMin, Tuning.HotPoneroCutMax) : rng.Range(Tuning.HotCutMin, Tuning.HotCutMax);
|
||||
return new HotOffer
|
||||
{
|
||||
Asset = asset, Qty = value / coinPrice, Value = value, Cash = (int)Math.Round(value * cut),
|
||||
Sting = rng.Chance(Tuning.HotSting + (crackdown ? Tuning.HotStingCrackdown : 0)),
|
||||
};
|
||||
}
|
||||
|
||||
/// <summary>收下:币进钱包,成本是付出的现金;PSC、CRT 按市值记污点,Ponero 不记。钓鱼执法不在这里处理。</summary>
|
||||
public static void Receive(Wallet w, HotOffer o)
|
||||
{
|
||||
w.Add(o.Asset, o.Qty);
|
||||
w.Basis += o.Cash;
|
||||
if (o.Asset != Assets.Ponero) w.Taint += o.Value;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,37 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
|
||||
namespace Decentralized.Domain
|
||||
{
|
||||
/// <summary>浏览器里的一条链上转账:区块、天、转出方、转入方、币种、数额、手续费。</summary>
|
||||
public sealed class LedgerEntry
|
||||
{
|
||||
public long Block;
|
||||
public int Day;
|
||||
public string From, To, Asset;
|
||||
public double Amount, Fee;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 全局账本:只记真实发生的转账(玩家钱包的每一笔进出,含合约调用和地址投毒的 0 币转入),不生成 NPC 流水;最新的在前,超过 <see cref="Tuning.LedgerMax"/> 条丢最旧的。
|
||||
/// </summary>
|
||||
public sealed class Ledger
|
||||
{
|
||||
public List<LedgerEntry> Entries = new List<LedgerEntry>();
|
||||
|
||||
public void Add(LedgerEntry e)
|
||||
{
|
||||
if (e == null || e.Amount < 0) return;
|
||||
Entries.Insert(0, e);
|
||||
if (Entries.Count > Tuning.LedgerMax) Entries.RemoveRange(Tuning.LedgerMax, Entries.Count - Tuning.LedgerMax);
|
||||
}
|
||||
|
||||
/// <summary>某个地址相关(转出或转入)的记录,最新的在前,最多 limit 条。address 为空时返回全部最近的。</summary>
|
||||
public List<LedgerEntry> Of(string address, int limit)
|
||||
{
|
||||
if (string.IsNullOrWhiteSpace(address)) return Entries.Take(limit).ToList();
|
||||
return Entries.Where(e => ChainAddress.Same(e.From, address) || ChainAddress.Same(e.To, address)).Take(limit).ToList();
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -4,6 +4,14 @@ using System.Linq;
|
||||
|
||||
namespace Decentralized.Domain
|
||||
{
|
||||
/// <summary>一次互换的报价:得到数量、经过几个池、相对中间价的损失(手续费加滑点)。</summary>
|
||||
public sealed class SwapQuote
|
||||
{
|
||||
public string From, To;
|
||||
public double In, Out, Impact;
|
||||
public int Hops;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 影响行情的游戏事件种类。接入层把游戏的新闻事件与派系行动映射到这里(例如全站停电、电力短缺 → Blackout)。
|
||||
/// </summary>
|
||||
@@ -16,35 +24,142 @@ namespace Decentralized.Domain
|
||||
public sealed class Market
|
||||
{
|
||||
public double Sentiment = 1.0;
|
||||
/// <summary>供给因子:出块奖励减半抬高挖矿成本,价格锚随之上移;减半前一周有预期行情。每晚向目标靠拢。</summary>
|
||||
public double Supply = 1.0;
|
||||
public List<Pool> Pools = new List<Pool>();
|
||||
/// <summary>开门时的参考价,夜间用它和收盘价算当日均价(合约的标记价)。</summary>
|
||||
public double OpenPrice = Tuning.PscStartPrice;
|
||||
/// <summary>玩家自己的现货大单把价格推高(正)或压低(负)的对数幅度,每晚随价格回归一起衰减。操纵检出和预测盘用它估"没有玩家时的价格"。</summary>
|
||||
public double PlayerPush;
|
||||
/// <summary>今天的插针(对数幅度,0 = 没有)和当晚回去的比例(0 = 真跌真涨)。</summary>
|
||||
public double Wick, WickBack;
|
||||
|
||||
public const double ArbRate = 0.5; // 非主交易对每晚被拉回参考价的比例
|
||||
public const double SideDepthShare = 0.3; // 非主交易对的深度占主交易对的比例
|
||||
/// <summary>夜间结算开始时:插针按比例回去(结算、预测盘读的是回去后的价格)。</summary>
|
||||
public void UndoWick(int day)
|
||||
{
|
||||
if (Wick == 0) return;
|
||||
Main.SetPrice(Price * Math.Exp(-Wick * WickBack), Tuning.PoolDepth(day));
|
||||
Wick = 0; WickBack = 0;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 插针:开门后价格瞬间被打到一边(大户扫强平、砸盘吸筹),大部分当晚回去,一部分是真的。
|
||||
/// 标记价用开门前的价格和收盘价平均,强平只吃一半。返回幅度(0 = 今天没有)。
|
||||
/// </summary>
|
||||
public double TryWick(Rng rng, int day)
|
||||
{
|
||||
Wick = 0; WickBack = 0;
|
||||
if (!rng.Chance(Tuning.WickChance)) return 0;
|
||||
double size = rng.Range(Tuning.WickMin, Tuning.WickMax) * (rng.Chance(0.5) ? 1 : -1);
|
||||
Wick = size;
|
||||
WickBack = rng.Chance(Tuning.WickReal) ? 0 : rng.Range(Tuning.WickRevertMin, Tuning.WickRevertMax);
|
||||
Main.SetPrice(Price * Math.Exp(size), Tuning.PoolDepth(day));
|
||||
return size;
|
||||
}
|
||||
public double NeutralPrice => Price * Math.Exp(-PlayerPush);
|
||||
/// <summary>被查概率:推价幅度(绝对值)超过 ManipFree 后随幅度升高。</summary>
|
||||
public static double ManipChance(double push)
|
||||
{
|
||||
push = Math.Abs(push);
|
||||
return push < Tuning.ManipFree ? 0 : Math.Min(Tuning.ManipMax, Tuning.ManipBase + Tuning.ManipSlope * (push - Tuning.ManipFree));
|
||||
}
|
||||
|
||||
public const double ArbRate = Tuning.SideArbRate; // 非主交易对每晚被拉回参考价的比例
|
||||
public const double SideDepthShare = Tuning.SideDepthShare; // 非主交易对的深度占主交易对的比例
|
||||
|
||||
public static Market CreateDefault(int day)
|
||||
{
|
||||
var m = new Market();
|
||||
double depth = Tuning.PoolDepth(day), p = Tuning.PscStartPrice;
|
||||
m.Pools.Add(Pool.Create(Venue.Exchange, Assets.PSC, Assets.CRC, p, depth, Tuning.ExchangeFee));
|
||||
m.Pools.Add(Pool.Create(Venue.Dex, Assets.PSC, Assets.CRT, p, depth * SideDepthShare, Tuning.DexFee));
|
||||
m.Pools.Add(Pool.Create(Venue.Dex, Assets.PSC, Assets.CRA, p, depth * SideDepthShare, Tuning.DexFee));
|
||||
m.Pools.Add(Pool.Create(Venue.Dex, Assets.CRT, Assets.CRC, 1, depth * SideDepthShare, Tuning.DexFee));
|
||||
m.Pools.Add(Pool.CreateBook(Venue.Exchange, Assets.PSC, Assets.CRC, p, depth, Tuning.ExchangeFee));
|
||||
m.Pools.Add(Pool.Create(Venue.Dex, Assets.PSC, Assets.CRC, p, depth * SideDepthShare, Tuning.DexFee));
|
||||
m.Pools.Add(Pool.CreateStable(Venue.Dex, Assets.CRT, Assets.CRC, 1, depth * SideDepthShare, Tuning.StableFee, Tuning.StableAmp));
|
||||
m.Pools.Add(Pool.CreateStable(Venue.Dex, Assets.CRA, Assets.CRC, 1, depth * SideDepthShare, Tuning.StableFee, Tuning.StableAmp));
|
||||
m.Pools.Add(Pool.Create(Venue.Dex, Assets.SPARK, Assets.CRC, Tuning.SparkStart, depth * Tuning.SparkDepthShare, Tuning.DexFee));
|
||||
m.AddPoinSpark(Tuning.SparkStart, day);
|
||||
return m;
|
||||
}
|
||||
|
||||
public Pool Main => Pools[0];
|
||||
|
||||
/// <summary>旧存档:稳定币对是恒定乘积池,按当前价换成 StableSwap 池;其他 DEX 池按新深度重设(不等到夜里)。</summary>
|
||||
public void UpgradeDexPools(int day)
|
||||
{
|
||||
for (int i = 0; i < Pools.Count; i++)
|
||||
{
|
||||
var p = Pools[i];
|
||||
if (p.Venue != Venue.Dex || p.Stable) continue;
|
||||
if (p.Base == Assets.CRT || p.Base == Assets.CRA)
|
||||
Pools[i] = Pool.CreateStable(Venue.Dex, p.Base, p.Quote, p.Price, Tuning.PoolDepth(day) * SideDepthShare, Tuning.StableFee, Tuning.StableAmp);
|
||||
else p.SetPrice(p.Price, Tuning.PoolDepth(day) * DepthShare(p));
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>Poinbase 的 SPARK/CRC 订单簿(旧存档没有时按当前价补上)。</summary>
|
||||
public void AddPoinSpark(double price, int day)
|
||||
{
|
||||
if (Find(Venue.Exchange, Assets.SPARK, Assets.CRC) == null)
|
||||
Pools.Add(Pool.CreateBook(Venue.Exchange, Assets.SPARK, Assets.CRC, price, Tuning.PoolDepth(day) * Tuning.PoinSparkDepthShare, Tuning.ExchangeFee));
|
||||
}
|
||||
|
||||
/// <summary>非主交易对的深度占主池的比例。</summary>
|
||||
private static double DepthShare(Pool p) =>
|
||||
p.Base != Assets.SPARK ? SideDepthShare : p.Venue == Venue.Exchange ? Tuning.PoinSparkDepthShare : Tuning.SparkDepthShare;
|
||||
|
||||
/// <summary>DEX 上 X/CRC 的池(所有币都以 CRC 计价)。</summary>
|
||||
public Pool DexPool(string asset) => Find(Venue.Dex, asset, Assets.CRC);
|
||||
|
||||
/// <summary>
|
||||
/// 任意两币互换的报价:CRC 在一端走一个池,否则 X → CRC → Y 两跳(两次手续费、滑点叠加)。
|
||||
/// 不改池子;没有路由(同币、没有池)返回 null。
|
||||
/// </summary>
|
||||
public SwapQuote Quote(string from, string to, double amount)
|
||||
{
|
||||
if (from == to || amount <= 0) return null;
|
||||
var a = from == Assets.CRC ? null : DexPool(from);
|
||||
var b = to == Assets.CRC ? null : DexPool(to);
|
||||
if ((from != Assets.CRC && a == null) || (to != Assets.CRC && b == null)) return null;
|
||||
double crc = a == null ? amount : a.QuoteOut(amount);
|
||||
double mid = a == null ? amount : amount * a.Price;
|
||||
double outAmt = b == null ? crc : b.BaseOut(crc);
|
||||
double ideal = b == null ? mid : mid / b.Price;
|
||||
return new SwapQuote { From = from, To = to, In = amount, Out = outAmt, Hops = (a != null ? 1 : 0) + (b != null ? 1 : 0), Impact = ideal > 0 ? Math.Max(0, 1 - outAmt / ideal) : 0 };
|
||||
}
|
||||
|
||||
/// <summary>成交:按 <see cref="Quote"/> 的路由改动池子,返回得到的数量(没有路由返回 0)。</summary>
|
||||
public double Swap(string from, string to, double amount)
|
||||
{
|
||||
if (Quote(from, to, amount) == null) return 0;
|
||||
double crc = from == Assets.CRC ? amount : DexPool(from).SellBase(amount);
|
||||
return to == Assets.CRC ? crc : DexPool(to).BuyBase(crc);
|
||||
}
|
||||
|
||||
public Pool Find(Venue venue, string baseAsset, string quote) =>
|
||||
Pools.FirstOrDefault(x => x.Venue == venue && x.Base == baseAsset && x.Quote == quote);
|
||||
|
||||
/// <summary>PSC 的参考价(信用点)。</summary>
|
||||
public double Price => Main.Price;
|
||||
|
||||
/// <summary>历次减半抽到的传导指数之和:价格锚的供给因子目标为 2^此值。</summary>
|
||||
public double HalvingLog;
|
||||
|
||||
/// <summary>减半当晚:抽本次的传导指数。</summary>
|
||||
public void OnHalving(Rng rng) => HalvingLog += Tuning.HalvingPassMin + rng.NextDouble() * (Tuning.HalvingPassMax - Tuning.HalvingPassMin);
|
||||
|
||||
/// <summary>供给因子的目标:已发生的减半各自抬高锚;减半前 7 天内再逐日加预期。</summary>
|
||||
public double SupplyTarget(int day)
|
||||
{
|
||||
double t = Math.Pow(2, HalvingLog);
|
||||
int toHalving = Tuning.HalvingDays - day % Tuning.HalvingDays; // 减半当晚 day % HalvingDays == 0,那天之后又是一个完整周期
|
||||
if (toHalving <= Tuning.HalvingRampDays) t *= 1 + Tuning.HalvingRamp * (Tuning.HalvingRampDays - toHalving + 1) / Tuning.HalvingRampDays;
|
||||
return t;
|
||||
}
|
||||
|
||||
public void UpdateSupply(int day) => Supply += (SupplyTarget(day) - Supply) * Tuning.SupplyAdjust;
|
||||
|
||||
public double Anchor(ICollection<MarketEvent> active)
|
||||
{
|
||||
double a = Tuning.PscStartPrice * Sentiment;
|
||||
double a = Tuning.PscStartPrice * Sentiment * Supply;
|
||||
if (active.Contains(MarketEvent.Blackout)) a *= 1.10;
|
||||
if (active.Contains(MarketEvent.Crackdown)) a *= 0.92;
|
||||
return a;
|
||||
@@ -66,11 +181,11 @@ namespace Decentralized.Domain
|
||||
OpenPrice = p;
|
||||
}
|
||||
|
||||
/// <summary>NPC 大户:每周约 2 笔、每笔 2,000–8,000 信用点,随机买或卖。返回成交额(正为买入),没有交易时为 0。</summary>
|
||||
/// <summary>NPC 大户:每周约 2 笔、每笔 <see cref="Tuning.WhaleMin"/>–<see cref="Tuning.WhaleMax"/> 信用点,随机买或卖。返回成交额(正为买入),没有交易时为 0。</summary>
|
||||
public double Whale(Rng rng)
|
||||
{
|
||||
if (!rng.Chance(2.0 / 7)) return 0;
|
||||
double size = rng.Range(2000.0, 8000.0);
|
||||
double size = rng.Range(Tuning.WhaleMin, Tuning.WhaleMax);
|
||||
if (rng.Chance(0.5)) { Main.BuyBase(size); return size; }
|
||||
Main.SellBase(size / Price);
|
||||
return -size;
|
||||
@@ -85,6 +200,8 @@ namespace Decentralized.Domain
|
||||
/// </summary>
|
||||
public void Night(ICollection<MarketEvent> active, Rng rng, int day, Func<string, double> stablePrice)
|
||||
{
|
||||
if (Wick != 0) { Main.SetPrice(Price * Math.Exp(-Wick * WickBack), Tuning.PoolDepth(day)); Wick = 0; WickBack = 0; }
|
||||
PlayerPush *= 1 - Tuning.Revert;
|
||||
Sentiment *= Math.Exp(Tuning.SentimentKappa * -Math.Log(Sentiment) + rng.Gauss() * Tuning.SentimentVol);
|
||||
double anchor = Anchor(active);
|
||||
double lp = Math.Log(Price);
|
||||
@@ -97,7 +214,15 @@ namespace Decentralized.Domain
|
||||
double baseCredits = pool.Base == Assets.PSC ? p : stablePrice(pool.Base);
|
||||
double quoteCredits = pool.Quote == Assets.PSC ? p : stablePrice(pool.Quote);
|
||||
if (quoteCredits <= 0) continue;
|
||||
pool.Revert(baseCredits / quoteCredits, ArbRate, depth * SideDepthShare / quoteCredits);
|
||||
double share = DepthShare(pool);
|
||||
// 稳定币对:参考价偏离挂钩超过界线时流动性变差(放大系数降低),回到挂钩附近恢复
|
||||
if (pool.Stable)
|
||||
{
|
||||
double dev = Math.Abs(baseCredits / quoteCredits - 1);
|
||||
pool.Amp = dev > Tuning.StableBrokenBand ? Tuning.StableAmpBroken : dev > Tuning.StableDepegBand ? Tuning.StableAmpDepeg : Tuning.StableAmp;
|
||||
if (dev > Tuning.StableBrokenBand) share *= Tuning.StableBrokenDepth;
|
||||
}
|
||||
pool.Revert(baseCredits / quoteCredits, ArbRate, depth * share / quoteCredits);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -13,6 +13,10 @@ namespace Decentralized.Domain
|
||||
public double Kj;
|
||||
public int Price;
|
||||
/// <summary>暴毙概率的品牌系数。</summary>
|
||||
/// <summary>档次:0 低端、1 中端、2 高端、3 旗舰(显卡)。实物特征(供电口、风扇数)只看档次。</summary>
|
||||
public int Tier;
|
||||
/// <summary>废片:只会作为假卡背后的真实芯片出现,不上架、不单独出现。低档次的卡也能被冒充靠它。</summary>
|
||||
public bool Scrap;
|
||||
public double DeathFactor;
|
||||
/// <summary>每天损耗的系数。</summary>
|
||||
public double WearFactor;
|
||||
@@ -25,23 +29,38 @@ namespace Decentralized.Domain
|
||||
|
||||
public static class Hardware
|
||||
{
|
||||
/// <summary>各档次的实物特征:供电口针数(旗舰是两个 8 针)与风扇数量。</summary>
|
||||
public static readonly string[] PowerPins = { "6", "8", "8", "8+8" };
|
||||
public static readonly int[] FanCount = { 1, 2, 3, 3 };
|
||||
/// <summary>各档次的供电口:0 = 6 针,1 = 8 针,2 = 双 8 针。</summary>
|
||||
public static readonly int[] PinClass = { 0, 1, 1, 2 };
|
||||
|
||||
public const string Probidia = "Probidia", Pmd = "PMD", RatDigg = "RatDigg";
|
||||
|
||||
public static readonly IReadOnlyDictionary<string, HardwareSpec> Specs = new[]
|
||||
{
|
||||
Gpu("RZX50", Probidia, 1.0, 4, 220), Gpu("RZX60", Probidia, 1.5, 5, 330), Gpu("RZX70", Probidia, 5.0, 12, 800),
|
||||
Gpu("RZX80Ti", Probidia, 8.0, 18, 1300), Gpu("RZX90", Probidia, 20.0, 30, 5000),
|
||||
Gpu("RZ470", Pmd, 0.8, 2.5, 170), Gpu("RZ580", Pmd, 1.2, 3, 250), Gpu("RZ6800", Pmd, 4.0, 8, 680),
|
||||
Gpu("RZ7900", Pmd, 15.0, 20, 4000),
|
||||
// 四个档次(低端、中端、高端、旗舰),两个牌子通用:型号只是显示名,性能和价格由「牌子 + 档次」决定
|
||||
Gpu("RTX60", Probidia, 0, 1.8, 4, 220), Gpu("RTX70", Probidia, 1, 5.0, 12, 800),
|
||||
Gpu("RTX80", Probidia, 2, 8.0, 18, 1300), Gpu("RTX90", Probidia, 3, 20.0, 30, 5000),
|
||||
Gpu("RX70", Pmd, 0, 1.4, 2.5, 170), Gpu("RX80", Pmd, 1, 4.0, 8, 680),
|
||||
Gpu("RX800", Pmd, 2, 8.0, 14, 1500), Gpu("RX900", Pmd, 3, 15.0, 20, 4000),
|
||||
Scrap("RX10", Pmd, 0, 0.3, 2, 60),
|
||||
Asic("M1", 50, 60, 11000), Asic("M2", 120, 110, 27000), Asic("M3", 300, 220, 72000),
|
||||
}.ToDictionary(s => s.Model);
|
||||
|
||||
private static HardwareSpec Gpu(string model, string brand, double h, double kj, int price) => new HardwareSpec
|
||||
private static HardwareSpec Gpu(string model, string brand, int tier, double h, double kj, int price) => new HardwareSpec
|
||||
{
|
||||
Model = model, Brand = brand, Hash = h, Kj = kj, Price = price,
|
||||
Model = model, Brand = brand, Tier = tier, Hash = h, Kj = kj, Price = price,
|
||||
DeathFactor = brand == Probidia ? 0.7 : 1.0, WearFactor = brand == Probidia ? 1.0 : 1.2,
|
||||
};
|
||||
|
||||
private static HardwareSpec Scrap(string model, string brand, int tier, double h, double kj, int price)
|
||||
{
|
||||
var s = Gpu(model, brand, tier, h, kj, price);
|
||||
s.Scrap = true;
|
||||
return s;
|
||||
}
|
||||
|
||||
private static HardwareSpec Asic(string model, double h, double kj, int price) => new HardwareSpec
|
||||
{
|
||||
Model = model, Brand = RatDigg, Hash = h, Kj = kj, Price = price, DeathFactor = 0.5, WearFactor = 0.8, Asic = true,
|
||||
@@ -84,15 +103,24 @@ namespace Decentralized.Domain
|
||||
public double Health = 100;
|
||||
public bool Dead;
|
||||
public bool Refurbished;
|
||||
/// <summary>外观;新卡(正规渠道)没有记录,按全新画。</summary>
|
||||
public CardLook Look;
|
||||
/// <summary>按当前健康度算出的外观。</summary>
|
||||
public CardLook Appearance => Look.Appearance(Health);
|
||||
|
||||
public HardwareSpec Label => Hardware.Specs[Model];
|
||||
public HardwareSpec Chip => Hardware.Specs[FakeOf ?? Model];
|
||||
|
||||
/// <summary>实物上的风扇数:对得上标称型号时是标称档次的,对不上(假卡的破绽)时是真实芯片的。</summary>
|
||||
public int ObservedCount => Hardware.FanCount[(Look.CountBad != 0 ? Chip : Label).Tier];
|
||||
/// <summary>实物上的供电口:0 = 6 针,1 = 8 针,2 = 双 8 针;规则同风扇数。</summary>
|
||||
public int ObservedPin => Hardware.PinClass[(Look.PinBad != 0 ? Chip : Label).Tier];
|
||||
|
||||
/// <summary>当前算力:健康 ≥ 50 时满算力,低于 50 线性降到健康 0 时的 60%。</summary>
|
||||
public double Hash(ModuleBonus b)
|
||||
{
|
||||
if (Dead) return 0;
|
||||
return Chip.Hash * (Health >= 50 ? 1.0 : 0.6 + 0.4 * Health / 50) * b.Hash;
|
||||
return Chip.Hash * (Health >= 50 ? 1.0 : 0.6 + 0.4 * Health / 50) * b.Hash * Appearance.HashFactor;
|
||||
}
|
||||
|
||||
public double Kj(ModuleBonus b) => Dead ? 0 : Chip.Kj * b.Kj;
|
||||
@@ -101,14 +129,14 @@ namespace Decentralized.Domain
|
||||
public double DeathChance(ModuleBonus b)
|
||||
{
|
||||
double p = Tuning.DeathBase + Tuning.DeathWorn * Math.Pow(1 - Health / 100, 2);
|
||||
return p * Label.DeathFactor * (FakeOf != null ? Tuning.FakeDeathFactor : 1) * b.Death;
|
||||
return p * Label.DeathFactor * (FakeOf != null ? Tuning.FakeDeathFactor : 1) * b.Death * Appearance.DeathFactor;
|
||||
}
|
||||
|
||||
/// <summary>一夜的损耗与暴毙判定;返回是否在今晚暴毙。</summary>
|
||||
public bool Night(ModuleBonus b, Rng rng)
|
||||
{
|
||||
if (Dead) return false;
|
||||
Health = Math.Max(0, Health - Label.WearFactor * b.Wear);
|
||||
Health = Math.Max(0, Health - Label.WearFactor * b.Wear * Appearance.WearFactor);
|
||||
if (rng.Chance(DeathChance(b)))
|
||||
{
|
||||
Dead = true;
|
||||
@@ -131,6 +159,10 @@ namespace Decentralized.Domain
|
||||
public sealed class Network
|
||||
{
|
||||
public double NpcHash = Tuning.NpcHash0;
|
||||
/// <summary>NPC 矿工每 H 的耗电(kJ):矿机时代到来后减半,他们能挖得更久,全网算力均衡点升高。</summary>
|
||||
public double NpcKj = Tuning.NpcKjPerH;
|
||||
public int EraDay = -1, EraWarnDay = -1;
|
||||
public bool EraWarned, EraDone;
|
||||
public double Reward = Tuning.BlockReward;
|
||||
/// <summary>停电、动荡等事件对 NPC 算力的可用比例。</summary>
|
||||
public double Availability = 1.0;
|
||||
@@ -140,7 +172,26 @@ namespace Decentralized.Domain
|
||||
{
|
||||
if (playerHash <= 0) return 0;
|
||||
double total = NpcHash * Availability + playerHash;
|
||||
return Reward * playerHash / total * (1 - Tuning.PoolFee);
|
||||
return Reward * playerHash / total * (1 - Tuning.PoolFee) * Scales.Mining;
|
||||
}
|
||||
|
||||
public enum EraStep { None, Warn, Start }
|
||||
|
||||
/// <summary>
|
||||
/// "矿机时代":第一次调用时在 EraMin–EraMax 天之间随机定一天(至少留出预兆的天数),提前 4–7 天预兆,到点 NPC 耗电效率翻倍,永久。
|
||||
/// 返回今晚发生的一步(预兆 / 开始)。
|
||||
/// </summary>
|
||||
public EraStep EraNight(int day, Rng rng)
|
||||
{
|
||||
if (EraDone) return EraStep.None;
|
||||
if (EraDay < 0)
|
||||
{
|
||||
EraDay = Math.Max(day + Tuning.EraWarnMax + 1, rng.Range(Tuning.EraMin, Tuning.EraMax));
|
||||
EraWarnDay = EraDay - rng.Range(Tuning.EraWarnMin, Tuning.EraWarnMax);
|
||||
}
|
||||
if (day >= EraDay) { NpcKj *= Tuning.EraKjMult; EraDone = true; return EraStep.Start; }
|
||||
if (!EraWarned && day >= EraWarnDay) { EraWarned = true; return EraStep.Warn; }
|
||||
return EraStep.None;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
@@ -151,7 +202,7 @@ namespace Decentralized.Domain
|
||||
if (day > 0 && day % Tuning.HalvingDays == 0) Reward /= 2;
|
||||
double total = NpcHash * Availability + playerHash;
|
||||
double perH = Reward * price / total;
|
||||
double ratio = perH / (Tuning.NpcKjPerH * Tuning.ElecPrice);
|
||||
double ratio = perH / (NpcKj * Tuning.ElecPrice);
|
||||
double adj = Math.Max(-Tuning.NpcAdj, Math.Min(Tuning.NpcAdj, Tuning.NpcAdj * (ratio / Tuning.NpcTargetRatio - 1)));
|
||||
NpcHash *= 1 + adj;
|
||||
}
|
||||
|
||||
@@ -0,0 +1,107 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
|
||||
namespace Decentralized.Domain
|
||||
{
|
||||
/// <summary>混币器里一笔在途的存入。</summary>
|
||||
public sealed class MixDeposit
|
||||
{
|
||||
public string Asset;
|
||||
public double Amount;
|
||||
/// <summary>存入时一并带走的污点与成本(信用点)。</summary>
|
||||
public double Taint, Basis;
|
||||
public int Rounds;
|
||||
public int ReadyDay;
|
||||
/// <summary>存入的钱包地址:到期提回这里。</summary>
|
||||
public string Wallet;
|
||||
}
|
||||
|
||||
/// <summary>一笔混币结束时的结果,供夜间日志使用。</summary>
|
||||
public sealed class MixResult
|
||||
{
|
||||
public bool Rugged;
|
||||
public string Asset;
|
||||
public double Amount, TaintBefore, TaintAfter;
|
||||
public bool Flagged;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 混币器:把币存进去,每轮扣手续费、降低污点,轮数 = 等待天数,到期提回同一个地址。
|
||||
/// 匿名集 = NPC 背景量 + 玩家存入量,玩家占比越大清洗效果越差。镇压事件开始时可能被制裁:
|
||||
/// 制裁期间提出的币视为被标记(出金审查按"来自混币器或被标记地址"加重,且地址被标记)。每晚有极小概率跑路。
|
||||
/// </summary>
|
||||
public sealed class Mixer
|
||||
{
|
||||
public List<MixDeposit> Pending = new List<MixDeposit>();
|
||||
public int SanctionedUntil = -1;
|
||||
/// <summary>提回的币最近一次从混币器出来的天数,用来给出金审查加重。</summary>
|
||||
public int LastReturnDay = -999;
|
||||
|
||||
public bool Sanctioned(int day) => day <= SanctionedUntil;
|
||||
|
||||
/// <summary>资金来自混币器:最近 AML 窗口内提回过币,或者被标记。</summary>
|
||||
public bool RecentlyMixed(int day) => day - LastReturnDay <= Tuning.AmlWindowDays;
|
||||
|
||||
/// <summary>一轮的清洗率:基准 × 匿名集系数。</summary>
|
||||
/// <summary>每轮手续费(剧情可能改动)。</summary>
|
||||
public static double Fee => Math.Min(0.5, Tuning.MixerFee * StoryMods.Current.MixerFee);
|
||||
|
||||
public static double RoundRate(double depositValue) => Tuning.MixerCleanRate * Tuning.MixerNpcVolume * StoryMods.Current.MixerVolume / (Tuning.MixerNpcVolume * StoryMods.Current.MixerVolume + Math.Max(0, depositValue));
|
||||
|
||||
/// <summary>存入:从钱包按价值比例带走污点与成本。轮数超出范围或余额不足返回 null。</summary>
|
||||
public MixDeposit Deposit(Wallet w, string asset, double amount, int rounds, int day, Func<string, double> price)
|
||||
{
|
||||
if (rounds < 1 || rounds > Tuning.MixerMaxRounds || amount <= 0 || w.Avail(asset) + 1e-9 < amount) return null;
|
||||
double value = amount * price(asset);
|
||||
if (value < Tuning.MixerMin) return null;
|
||||
double total = w.Value(price);
|
||||
double share = total > 0 ? Math.Min(1, value / total) : 0;
|
||||
double taint = w.Taint * share, basis = w.Basis * share;
|
||||
w.Add(asset, -amount);
|
||||
w.Taint -= taint;
|
||||
w.Basis -= basis;
|
||||
var d = new MixDeposit { Asset = asset, Amount = amount, Taint = taint, Basis = basis, Rounds = rounds, ReadyDay = day + rounds, Wallet = w.Address };
|
||||
Pending.Add(d);
|
||||
return d;
|
||||
}
|
||||
|
||||
/// <summary>镇压事件开始:有一定概率被制裁,持续若干天。</summary>
|
||||
public void OnEvent(MarketEvent ev, int day, Rng rng)
|
||||
{
|
||||
if (ev == MarketEvent.Crackdown && rng.Chance(Math.Min(1, Tuning.MixerSanctionChance * StoryMods.Current.Sanction(day)))) SanctionedUntil = day + Tuning.MixerSanctionDays;
|
||||
}
|
||||
|
||||
/// <summary>每晚:到期的存入提回钱包(污点按轮数降低),在途的各有小概率跑路。</summary>
|
||||
public List<MixResult> Night(Wallet w, int day, Func<string, double> price, Rng rng) => Night(_ => w, day, price, rng);
|
||||
|
||||
/// <summary>每晚(多钱包):到期的存入按存入时的地址提回原钱包。</summary>
|
||||
public List<MixResult> Night(Func<string, Wallet> wallet, int day, Func<string, double> price, Rng rng)
|
||||
{
|
||||
var results = new List<MixResult>();
|
||||
foreach (var d in Pending.ToList())
|
||||
{
|
||||
if (rng.Chance(Scales.R(Tuning.MixerRugChance * StoryMods.Current.MixerRug)))
|
||||
{
|
||||
Pending.Remove(d);
|
||||
results.Add(new MixResult { Rugged = true, Asset = d.Asset, Amount = d.Amount });
|
||||
continue;
|
||||
}
|
||||
if (day < d.ReadyDay) continue;
|
||||
Pending.Remove(d);
|
||||
double rate = RoundRate(d.Amount * price(d.Asset));
|
||||
double taint = d.Taint * Math.Pow(1 - rate, d.Rounds);
|
||||
double amount = d.Amount * Math.Pow(1 - Fee, d.Rounds);
|
||||
bool flagged = Sanctioned(day);
|
||||
var w = wallet(d.Wallet);
|
||||
w.Add(d.Asset, amount);
|
||||
w.Taint += taint;
|
||||
w.Basis += d.Basis;
|
||||
if (flagged) w.Flagged = true;
|
||||
LastReturnDay = day;
|
||||
results.Add(new MixResult { Asset = d.Asset, Amount = amount, TaintBefore = d.Taint, TaintAfter = taint, Flagged = flagged });
|
||||
}
|
||||
return results;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,251 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
|
||||
namespace Decentralized.Domain
|
||||
{
|
||||
/// <summary>永续合约的一个净仓位。Size 是标的数量,Margin 是保证金(CRC,信用点等值),Taint / Basis 是存入时带来的污点与成本。</summary>
|
||||
public sealed class PerpPosition
|
||||
{
|
||||
public string Product;
|
||||
public bool Long;
|
||||
public double Size, Entry, Margin, Taint, Basis;
|
||||
|
||||
public double Notional(double price) => Size * price;
|
||||
public double Pnl(double price) => (Long ? 1 : -1) * Size * (price - Entry);
|
||||
public double Equity(double price) => Margin + Pnl(price);
|
||||
public double Leverage => Margin > 0 ? Size * Entry / Margin : 0;
|
||||
|
||||
/// <summary>强平价:权益跌到名义价值的维持比例时。</summary>
|
||||
public double LiqPrice => Long
|
||||
? Math.Max(0, (Size * Entry - Margin) / (Size * (1 - Tuning.PerpMaint)))
|
||||
: (Margin + Size * Entry) / (Size * (1 + Tuning.PerpMaint));
|
||||
}
|
||||
|
||||
public enum PerpResult { Ok, Banned, Debt, Leverage, Size, Funds, Opposite, NoPosition, Margin, Thin, Single }
|
||||
|
||||
/// <summary>夜间发生的事:强平、自动减仓、催收没收、核销。</summary>
|
||||
public sealed class PerpEvent
|
||||
{
|
||||
public string Kind; // liq / adl / seize / writeoff / interest / wipe
|
||||
public string Product;
|
||||
public bool Long;
|
||||
public double Amount; // 损失、减记、或欠款(信用点);wipe 是全网爆仓的名义价值(含玩家)
|
||||
public int Count; // wipe:爆仓人数(含玩家)
|
||||
public double Move; // wipe:标记价的涨跌幅
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Poinbase 永续合约(PSC-PERP、SPARK-PERP):保证金用 Poinbase 账户里的 CRC,一个品种一个净仓位。
|
||||
/// 标记价是当日均价,强平只在夜间检查(白天插针不触发)。强平后的剩余权益进保险基金,权益为负先由基金垫付,
|
||||
/// 基金不够的缺口记成玩家的欠款。NPC 仓位随行情爆仓:大部分正常爆仓,剩余保证金进基金;行情越快穿仓越多,缺口由基金垫付。
|
||||
/// 基金见底时盈利的仓位被自动减仓(盈利打折)。
|
||||
/// 欠款每天计息,每晚先用账户里的 CRC 还;逾期没还清由接入层没收物品抵债,剩下的核销并拉黑永续账户一段时间。
|
||||
/// </summary>
|
||||
public sealed class PerpBook
|
||||
{
|
||||
public List<PerpPosition> Positions = new List<PerpPosition>();
|
||||
public double InsuranceFund = Tuning.PerpFund0;
|
||||
public double Debt;
|
||||
public int DebtSince = -1, BannedUntil = -1;
|
||||
public Dictionary<string, List<double>> Marks = new Dictionary<string, List<double>>();
|
||||
public Dictionary<string, double> Funding = new Dictionary<string, double>();
|
||||
/// <summary>资金费系数(费率 = 系数 × 标记价偏离 7 日均价的比例)。默认取配置,模拟里用来校准。</summary>
|
||||
public double FundCoef = Tuning.PerpFundCoef;
|
||||
/// <summary>成交深度倍数(滑点 = 名义价值 / (倍数 × 永续深度)),模拟里用来校准。</summary>
|
||||
public double DepthMult = Tuning.PerpDepthMult;
|
||||
|
||||
/// <summary>成交价:买入(开多、平空)往上滑,卖出往下滑,滑点随名义价值占永续深度的比例增大,封顶 50%。</summary>
|
||||
public double Exec(double price, double notional, bool buy, int day)
|
||||
{
|
||||
double slip = Math.Min(0.5, notional / (DepthMult * Tuning.PerpDepth(day)));
|
||||
return price * (1 + (buy ? slip : -slip));
|
||||
}
|
||||
|
||||
public static readonly string[] Products = { "PSC", "SPARK" };
|
||||
public static int MaxLeverage(string product) => product == "SPARK" ? Tuning.PerpSparkLev : Tuning.PerpPscLev;
|
||||
public static double MaxNotional(string product) => product == "SPARK" ? Tuning.PerpSparkCap : Tuning.PerpPscCap;
|
||||
|
||||
public PerpPosition Of(string product) => Positions.Find(p => p.Product == product);
|
||||
public bool Banned(int day) => day <= BannedUntil;
|
||||
public double Rate(string product) => Funding.TryGetValue(product, out var r) ? r : 0;
|
||||
|
||||
private static double Share(Wallet acct, double amount, Func<string, double> price)
|
||||
{
|
||||
double total = acct.Value(price);
|
||||
return total > 0 ? Math.Min(1, amount * price(Assets.CRC) / total) : 0;
|
||||
}
|
||||
|
||||
/// <summary>开仓(同一时间只有一个仓位,已有仓位时只能 <see cref="AddMargin"/>):保证金 + 手续费从账户的 CRC 里扣,污点与成本按保证金的价值比例随保证金进仓位。</summary>
|
||||
public PerpResult Open(Wallet acct, string product, bool isLong, double margin, int leverage, double price, int day, Func<string, double> pr)
|
||||
{
|
||||
if (Banned(day)) return PerpResult.Banned;
|
||||
if (Debt > 1e-9) return PerpResult.Debt;
|
||||
if (leverage < 1 || leverage > MaxLeverage(product)) return PerpResult.Leverage;
|
||||
if (margin <= 0 || price <= 0) return PerpResult.Margin;
|
||||
var pos = Of(product);
|
||||
if (pos != null && pos.Long != isLong) return PerpResult.Opposite;
|
||||
if (Positions.Count > 0) return PerpResult.Single; // 只支持逐仓、一个仓位:有仓位后只能追加保证金
|
||||
double notional = margin * leverage, fee = notional * Tuning.PerpFee;
|
||||
double spot = price;
|
||||
price = Exec(price, notional, isLong, day);
|
||||
if ((pos?.Notional(price) ?? 0) + notional > MaxNotional(product) + 1e-9) return PerpResult.Size;
|
||||
if (acct.Avail(Assets.CRC) + 1e-9 < margin + fee) return PerpResult.Funds;
|
||||
// 滑点太大:按现价算权益已经低于强平线(再留一点余地),开了就是被强平
|
||||
double sizeNew = notional / price, sizeAll = (pos?.Size ?? 0) + sizeNew;
|
||||
double entryAll = ((pos?.Size ?? 0) * (pos?.Entry ?? 0) + sizeNew * price) / sizeAll;
|
||||
double eq0 = (pos?.Margin ?? 0) + margin + (isLong ? 1 : -1) * sizeAll * (spot - entryAll);
|
||||
if (eq0 < (Tuning.PerpMaint + Tuning.PerpOpenBuffer) * sizeAll * spot) return PerpResult.Thin;
|
||||
double share = Share(acct, margin, pr);
|
||||
double taint = acct.Taint * share, basis = acct.Basis * share;
|
||||
acct.Add(Assets.CRC, -(margin + fee)); acct.Taint -= taint; acct.Basis -= basis;
|
||||
InsuranceFund += fee * Tuning.PerpFeeToFund;
|
||||
if (pos == null) Positions.Add(pos = new PerpPosition { Product = product, Long = isLong, Entry = price });
|
||||
double size = notional / price;
|
||||
pos.Entry = (pos.Size * pos.Entry + size * price) / (pos.Size + size);
|
||||
pos.Size += size; pos.Margin += margin; pos.Taint += taint; pos.Basis += basis;
|
||||
return PerpResult.Ok;
|
||||
}
|
||||
|
||||
/// <summary>追加保证金(不收手续费),把强平价推远。</summary>
|
||||
public PerpResult AddMargin(Wallet acct, string product, double amount, Func<string, double> pr)
|
||||
{
|
||||
var pos = Of(product);
|
||||
if (pos == null) return PerpResult.NoPosition;
|
||||
if (amount <= 0) return PerpResult.Margin;
|
||||
if (acct.Avail(Assets.CRC) + 1e-9 < amount) return PerpResult.Funds;
|
||||
double share = Share(acct, amount, pr);
|
||||
double taint = acct.Taint * share, basis = acct.Basis * share;
|
||||
acct.Add(Assets.CRC, -amount); acct.Taint -= taint; acct.Basis -= basis;
|
||||
pos.Margin += amount; pos.Taint += taint; pos.Basis += basis;
|
||||
return PerpResult.Ok;
|
||||
}
|
||||
|
||||
/// <summary>平仓(按白天的现价):权益减手续费回到账户,污点按剩下的比例退回,盈利是干净的新币。权益不够付时缺口按穿仓处理。返回回到账户的 CRC。</summary>
|
||||
public double Close(Wallet acct, string product, double price, int day, out double deficit)
|
||||
{
|
||||
deficit = 0;
|
||||
var pos = Of(product);
|
||||
if (pos == null) return 0;
|
||||
Positions.Remove(pos);
|
||||
price = Exec(price, pos.Notional(price), !pos.Long, day);
|
||||
double fee = pos.Notional(price) * Tuning.PerpFee;
|
||||
double payout = pos.Equity(price) - fee;
|
||||
InsuranceFund += Math.Min(fee, Math.Max(0, pos.Equity(price))) * Tuning.PerpFeeToFund;
|
||||
if (payout < 0) { deficit = -payout; Cover(deficit, day); return 0; }
|
||||
Return(acct, pos, payout);
|
||||
return payout;
|
||||
}
|
||||
|
||||
private void Return(Wallet acct, PerpPosition pos, double payout)
|
||||
{
|
||||
double keep = pos.Margin > 0 ? Math.Min(1, payout / pos.Margin) : 0;
|
||||
acct.Add(Assets.CRC, payout); acct.Taint += pos.Taint * keep; acct.Basis += pos.Basis * keep;
|
||||
}
|
||||
|
||||
/// <summary>穿仓缺口:保险基金先垫,不够的记成欠款。</summary>
|
||||
private double Cover(double deficit, int day)
|
||||
{
|
||||
double take = Math.Min(InsuranceFund, deficit);
|
||||
InsuranceFund -= take;
|
||||
double rest = deficit - take;
|
||||
if (rest > 1e-9) { Debt += rest; if (DebtSince < 0) DebtSince = day; }
|
||||
return rest;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// NPC 仓位在一晚涨跌幅 move 下对保险基金的净流入(可为负),以及爆仓的名义价值。oi 是亏损一侧的持仓。
|
||||
/// 爆仓量 = oi × min(1, move / PerpNpcLiqScale);其中穿仓的比例随涨跌幅升高,正常爆仓交出剩余保证金,穿仓的缺口由基金垫付。
|
||||
/// </summary>
|
||||
public static double NpcFlow(double move, double oi, out double liquidated)
|
||||
{
|
||||
move = Math.Abs(move);
|
||||
liquidated = oi * Math.Min(1, move / Tuning.PerpNpcLiqScale);
|
||||
double bank = Math.Min(Tuning.PerpNpcBankMax, Tuning.PerpNpcBankBase + Tuning.PerpNpcBankSlope * Math.Max(0, move - Tuning.PerpNpcBankFree));
|
||||
return liquidated * ((1 - bank) * Tuning.PerpNpcLeft - bank * move * Tuning.PerpNpcGap);
|
||||
}
|
||||
|
||||
/// <summary>NPC 在某个品种上单边的持仓(信用点名义价值)。</summary>
|
||||
public static double NpcOi(string product, int day) => Tuning.PerpNpcOi * Tuning.PoolDepth(day) * (product == "SPARK" ? Tuning.SparkDepthShare : 1);
|
||||
|
||||
/// <summary>
|
||||
/// 夜间结算。marks:各品种今天的标记价(日均价)。顺序:资金费 → NPC 爆仓与穿仓进出基金 → 强平 → 基金见底时自动减仓盈利仓位 →
|
||||
/// 欠款计息并用账户 CRC 偿还 → 逾期的触发没收。标记价涨跌达到 <see cref="Tuning.PerpNewsMove"/> 的品种另记一条 wipe(全网爆仓,含玩家)。
|
||||
/// </summary>
|
||||
public List<PerpEvent> Night(int day, IDictionary<string, double> marks, Wallet acct, Func<string, double> pr)
|
||||
{
|
||||
var evs = new List<PerpEvent>();
|
||||
var wipes = new Dictionary<string, PerpEvent>();
|
||||
bool adl = false;
|
||||
foreach (var kv in marks)
|
||||
{
|
||||
string product = kv.Key; double mark = kv.Value;
|
||||
if (!Marks.TryGetValue(product, out var hist)) Marks[product] = hist = new List<double>();
|
||||
double prev = hist.Count > 0 ? hist[hist.Count - 1] : mark;
|
||||
double rate = 0;
|
||||
if (hist.Count >= 3) rate = Math.Max(-Tuning.PerpFundCap, Math.Min(Tuning.PerpFundCap, FundCoef * (mark / hist.Average() - 1)));
|
||||
Funding[product] = rate;
|
||||
hist.Add(mark); if (hist.Count > 7) hist.RemoveAt(0);
|
||||
var pos = Of(product);
|
||||
if (pos != null) pos.Margin -= (pos.Long ? 1 : -1) * rate * pos.Notional(mark);
|
||||
double ret = prev > 0 ? mark / prev - 1 : 0;
|
||||
InsuranceFund += NpcFlow(ret, NpcOi(product, day), out double liq);
|
||||
if (Math.Abs(ret) >= Tuning.PerpNewsMove)
|
||||
wipes[product] = new PerpEvent { Kind = "wipe", Product = product, Long = ret < 0, Amount = liq, Count = (int)Math.Round(liq / Tuning.PerpNpcAvgPos), Move = ret };
|
||||
}
|
||||
if (InsuranceFund < 0) { InsuranceFund = 0; adl = true; }
|
||||
foreach (var pos in Positions.ToList())
|
||||
{
|
||||
if (!marks.TryGetValue(pos.Product, out var mark)) continue;
|
||||
double eq = pos.Equity(mark), notional = pos.Notional(mark);
|
||||
if (eq >= Tuning.PerpMaint * notional) continue;
|
||||
Positions.Remove(pos);
|
||||
double rem = eq - Tuning.PerpLiqFee * notional;
|
||||
if (rem >= 0) InsuranceFund += rem; else Cover(-rem, day);
|
||||
evs.Add(new PerpEvent { Kind = "liq", Product = pos.Product, Long = pos.Long, Amount = pos.Margin });
|
||||
if (wipes.TryGetValue(pos.Product, out var wp) && wp.Long == pos.Long) { wp.Amount += notional; wp.Count++; }
|
||||
}
|
||||
evs.AddRange(wipes.Values);
|
||||
if (adl)
|
||||
foreach (var pos in Positions.ToList())
|
||||
{
|
||||
if (!marks.TryGetValue(pos.Product, out var mark) || pos.Pnl(mark) <= 0) continue;
|
||||
double pnl = pos.Pnl(mark), cut = pnl * Tuning.PerpAdlHaircut;
|
||||
Positions.Remove(pos);
|
||||
Return(acct, pos, pos.Margin + pnl - cut);
|
||||
evs.Add(new PerpEvent { Kind = "adl", Product = pos.Product, Long = pos.Long, Amount = cut });
|
||||
}
|
||||
if (Debt > 1e-9)
|
||||
{
|
||||
double interest = Debt * Tuning.PerpDebtInterest;
|
||||
Debt += interest;
|
||||
double repay = Math.Min(Debt, acct.Avail(Assets.CRC));
|
||||
if (repay > 1e-9)
|
||||
{
|
||||
double share = Share(acct, repay, pr);
|
||||
double taint = acct.Taint * share, basis = acct.Basis * share;
|
||||
acct.Add(Assets.CRC, -repay); acct.Taint -= taint; acct.Basis -= basis;
|
||||
Debt -= repay;
|
||||
evs.Add(new PerpEvent { Kind = "repaid", Amount = repay });
|
||||
}
|
||||
if (Debt < 1e-6) { Debt = 0; DebtSince = -1; }
|
||||
else
|
||||
{
|
||||
evs.Add(new PerpEvent { Kind = "interest", Amount = Debt });
|
||||
if (day - DebtSince >= Tuning.PerpDebtDays) evs.Add(new PerpEvent { Kind = "seize", Amount = Debt });
|
||||
}
|
||||
}
|
||||
return evs;
|
||||
}
|
||||
|
||||
/// <summary>没收物品抵债之后:抵掉的价值从欠款里扣,还剩的核销并拉黑永续账户。返回核销的数额。</summary>
|
||||
public double ApplySeizure(double value, int day)
|
||||
{
|
||||
Debt -= value;
|
||||
double writtenOff = Math.Max(0, Debt);
|
||||
if (writtenOff > 0.5) BannedUntil = day + Tuning.PerpBanDays;
|
||||
Debt = 0; DebtSince = -1;
|
||||
return writtenOff;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,83 @@
|
||||
using System;
|
||||
|
||||
namespace Decentralized.Domain
|
||||
{
|
||||
/// <summary>夜间发生的事。Kind:collapse(付不出利息,挤兑)/ reported(被举报);Amount 是被没收的池子。</summary>
|
||||
public sealed class PonziEvent
|
||||
{
|
||||
public string Kind;
|
||||
public double Amount;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 高息理财(庞氏):玩家定一个日息,下层的人按日息和下层声望往池子里存 CRC。每晚先拿新存入的钱付利息,不够的从发行人钱包的 CRC 补,
|
||||
/// 补不上就挤兑崩盘;池子越大、日息越高越容易被举报,被举报同样崩盘。崩盘时池子被没收;玩家也可以随时卷走池子(污点全额)。
|
||||
/// 每个存档只能开一次。
|
||||
/// </summary>
|
||||
public sealed class Ponzi
|
||||
{
|
||||
public bool Open, Done;
|
||||
public double Rate, Pool, OwnPaid, AdCost, Inflow;
|
||||
/// <summary>发行人的钱包地址:宣传费、垫付的利息从它出,卷走的池子进它。</summary>
|
||||
public string Wallet;
|
||||
public int OpenDay = -1;
|
||||
|
||||
public static double Cap(int day) => Tuning.PonziCap0 + Tuning.PonziCapPerDay * day;
|
||||
|
||||
/// <summary>每晚新存入(均值):基数随天数,日息高于 4% 时按指数放大,下层声望越高越多。</summary>
|
||||
public static double InflowMean(int day, double rate, int lowerRep) =>
|
||||
(Tuning.PonziBase0 + Tuning.PonziBasePerDay * day) * Math.Pow(rate / 0.04, Tuning.PonziRateExp) * Math.Max(0.3, Math.Min(1.5, 0.5 + lowerRep / 100.0));
|
||||
|
||||
public static double ReportChance(double rate, double pool, int day) =>
|
||||
Math.Min(0.9, Tuning.PonziReport0 + Tuning.PonziReportRate * rate + Tuning.PonziReportSize * Math.Min(1, pool / Cap(day)));
|
||||
|
||||
public bool CanOpen(int day) => !Open && !Done && day >= Tuning.PonziMinDay;
|
||||
|
||||
/// <summary>开张:宣传费从发行人钱包的 CRC 里扣。</summary>
|
||||
public bool Start(Wallet acct, double rate, int day)
|
||||
{
|
||||
if (!CanOpen(day) || acct.Avail(Assets.CRC) + 1e-9 < Tuning.PonziAdCost) return false;
|
||||
acct.Add(Assets.CRC, -Tuning.PonziAdCost);
|
||||
Open = true; Rate = rate; Pool = 0; OwnPaid = 0; AdCost = Tuning.PonziAdCost; OpenDay = day; Wallet = acct.Address;
|
||||
return true;
|
||||
}
|
||||
|
||||
/// <summary>夜间结算。返回崩盘 / 被举报事件(没有事就返回 null)。</summary>
|
||||
public PonziEvent Night(int day, int lowerRep, Wallet acct, Rng rng)
|
||||
{
|
||||
if (!Open) return null;
|
||||
double mean = InflowMean(day, Rate, lowerRep);
|
||||
double inflow = Math.Min(Cap(day) - Pool, mean * rng.Range(0.6, 1.4));
|
||||
inflow = Math.Max(0, inflow); Inflow = inflow;
|
||||
double interest = Pool * Rate;
|
||||
double fromInflow = Math.Min(interest, inflow), rest = interest - fromInflow;
|
||||
if (rest > acct.Avail(Assets.CRC) + 1e-9)
|
||||
{
|
||||
var ev = new PonziEvent { Kind = "collapse", Amount = Pool + inflow - fromInflow };
|
||||
Open = false; Done = true; Pool = 0;
|
||||
return ev;
|
||||
}
|
||||
if (rest > 0) { acct.Add(Assets.CRC, -rest); OwnPaid += rest; }
|
||||
Pool += inflow - fromInflow;
|
||||
Pool -= Pool * Tuning.PonziWithdraw;
|
||||
if (rng.Chance(ReportChance(Rate, Pool, day)))
|
||||
{
|
||||
var ev = new PonziEvent { Kind = "reported", Amount = Pool };
|
||||
Open = false; Done = true; Pool = 0;
|
||||
return ev;
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
/// <summary>卷走:池子全部进账户,污点全额(骗局所得)。返回卷走的数额。</summary>
|
||||
/// <summary>卷走:池子全部进发行人钱包,污点全额(骗局所得)。</summary>
|
||||
public double Rug(Wallet acct)
|
||||
{
|
||||
if (!Open) return 0;
|
||||
double take = Pool;
|
||||
acct.Add(Assets.CRC, take); acct.Taint += take;
|
||||
Open = false; Done = true; Pool = 0;
|
||||
return take;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,447 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
|
||||
namespace Decentralized.Domain
|
||||
{
|
||||
public enum PredictKind { Event, Faction, Purity, Price, Gas, Cra, Era }
|
||||
|
||||
public enum PredictResult { Ok, Closed, Amount, Funds, Cap, Opposite, NoPosition }
|
||||
|
||||
/// <summary>
|
||||
/// 一个盘口:问一个是非题,开盘当天可以买卖,窗口(FromDay..ToDay)里的结果由游戏或本 mod 的数值决定,ToDay 夜间结算。
|
||||
/// 定价用 LMSR:初始价等于先验概率 P0,流动性参数 B 按开盘日的单盘额度(<see cref="Budget"/>)定,与先验无关;
|
||||
/// 额度决定份额上限(限制内幕单能赚多少)和内幕消息的价格。
|
||||
/// </summary>
|
||||
public sealed class PredictMarket
|
||||
{
|
||||
public int Id;
|
||||
public PredictKind Kind;
|
||||
/// <summary>事件 / 派系标识;纯度盘是 "gutter" 或 "rust";行情盘是 "PSC"。</summary>
|
||||
public string Key, Title;
|
||||
/// <summary>阈值(纯度、价格盘)。</summary>
|
||||
public double Param;
|
||||
public int OpenDay, FromDay, ToDay;
|
||||
public double P0, B, QYes, QNo;
|
||||
/// <summary>单盘额度(开盘日的 <see cref="LossFor"/>)。旧存档里的盘口没有这个字段,按当时"额度 = B × ln(1/先验)"回推。</summary>
|
||||
public double Budget;
|
||||
/// <summary>昨晚消息反应之前的价格(-1 = 还没反应过):列表里显示涨跌,让玩家看到消息怎样推动价格。</summary>
|
||||
public double PrevP = -1;
|
||||
/// <summary>-1 未结算,0 否,1 是,2 作废(缺观测数据,退还本金)。</summary>
|
||||
public int Outcome = -1;
|
||||
|
||||
public double Loss => Budget > 0 ? Budget : B * Math.Log(1 / Math.Min(P0, 1 - P0));
|
||||
public double ShareCap => Tuning.PredictCap * Loss;
|
||||
public bool IsOpen(int day) => Outcome < 0 && day < FromDay;
|
||||
public double PYes => 1 / (1 + Math.Exp((QNo - QYes) / B));
|
||||
|
||||
public static double LossFor(int day) => Tuning.PredictLoss0 + Tuning.PredictLossPerDay * day;
|
||||
|
||||
public static PredictMarket Create(int id, PredictKind kind, string key, string title, double param, int openDay, int fromDay, int toDay, double p0)
|
||||
{
|
||||
p0 = Math.Max(Tuning.PredictPMin, Math.Min(Tuning.PredictPMax, p0));
|
||||
double budget = LossFor(openDay), b = Tuning.PredictDepth * budget / Math.Log(2);
|
||||
return new PredictMarket { Id = id, Kind = kind, Key = key, Title = title, Param = param, OpenDay = openDay, FromDay = fromDay, ToDay = toDay, P0 = p0, B = b, Budget = budget, QYes = b * Math.Log(p0 / (1 - p0)) };
|
||||
}
|
||||
|
||||
/// <summary>LMSR 成本函数(数值稳定写法)。</summary>
|
||||
public double C(double qy, double qn)
|
||||
{
|
||||
double m = Math.Max(qy, qn);
|
||||
return m + B * Math.Log(Math.Exp((qy - m) / B) + Math.Exp((qn - m) / B));
|
||||
}
|
||||
|
||||
/// <summary>某一边买入 shares 份要付的成本(不含手续费)。</summary>
|
||||
public double BuyCost(bool yes, double shares) => yes ? C(QYes + shares, QNo) - C(QYes, QNo) : C(QYes, QNo + shares) - C(QYes, QNo);
|
||||
|
||||
/// <summary>某一边卖出 shares 份能收回的金额(不含手续费)。</summary>
|
||||
public double SellValue(bool yes, double shares) => yes ? C(QYes, QNo) - C(QYes - shares, QNo) : C(QYes, QNo) - C(QYes, QNo - shares);
|
||||
|
||||
/// <summary>花 cost(不含手续费)能买到的份数:LMSR 成本函数的闭式反解。</summary>
|
||||
public double SharesFor(bool yes, double cost)
|
||||
{
|
||||
double y = yes ? QYes : QNo, o = yes ? QNo : QYes;
|
||||
double m = Math.Max(y, o);
|
||||
double a = Math.Exp((y - m) / B), oo = Math.Exp((o - m) / B);
|
||||
double x = Math.Exp(Math.Min(cost / B, 700)) * (a + oo) - oo;
|
||||
return m + B * Math.Log(x) - y;
|
||||
}
|
||||
|
||||
public double PriceOf(bool yes) => yes ? PYes : 1 - PYes;
|
||||
}
|
||||
|
||||
/// <summary>玩家在某个盘口的持仓(一个盘口只能持有一边)。Insider 是内幕单买入的份数。</summary>
|
||||
public sealed class PredictPos
|
||||
{
|
||||
public int Market;
|
||||
/// <summary>持仓所在的钱包地址(下注签名的钱包,结算和卖出都回到它)。</summary>
|
||||
public string Wallet;
|
||||
public bool Yes;
|
||||
public double Shares, Cost, Taint, Basis, Insider;
|
||||
}
|
||||
|
||||
/// <summary>情报贩子卖的内幕消息:对某个盘口给出"是 / 否"的说法,三档准确率,可能是假的(与真相相反)。</summary>
|
||||
public sealed class PredictTip
|
||||
{
|
||||
public int Market, Tier;
|
||||
public bool Claim;
|
||||
public double Paid;
|
||||
}
|
||||
|
||||
public sealed class PredictStat
|
||||
{
|
||||
public int Count, Hits;
|
||||
public double SumP0;
|
||||
public double AvgP0 => Count > 0 ? SumP0 / Count : 0;
|
||||
public double HitRate => Count > 0 ? Hits / (double)Count : 0;
|
||||
}
|
||||
|
||||
/// <summary>一次夜间价格反应。</summary>
|
||||
public sealed class PredictMove
|
||||
{
|
||||
public PredictMarket Market;
|
||||
public double From, To;
|
||||
}
|
||||
|
||||
/// <summary>结算记录(盘口列表下面的"最近结果")。</summary>
|
||||
public sealed class PredictRecord
|
||||
{
|
||||
public int Day;
|
||||
public string Title;
|
||||
public int Outcome;
|
||||
public double Pnl;
|
||||
public bool Held;
|
||||
}
|
||||
|
||||
/// <summary>夜间结算发生的事。Kind:win / lose / void / caught。</summary>
|
||||
public sealed class PredictEvent
|
||||
{
|
||||
public string Kind, Title;
|
||||
public PredictMarket Market;
|
||||
public double Amount, Fraud;
|
||||
}
|
||||
|
||||
/// <summary>候选盘口(接入层按游戏当前状态给出):先验概率按窗口算。</summary>
|
||||
public sealed class PredictCandidate
|
||||
{
|
||||
public PredictKind Kind;
|
||||
public string Key, Title;
|
||||
public double Param;
|
||||
/// <summary>true:只问明天一天(纯度盘)。</summary>
|
||||
public bool Tomorrow;
|
||||
public Func<int, int, double> Prob;
|
||||
}
|
||||
|
||||
public sealed class PredictBook
|
||||
{
|
||||
public List<PredictMarket> Markets = new List<PredictMarket>();
|
||||
public List<PredictPos> Positions = new List<PredictPos>();
|
||||
public List<PredictRecord> Recent = new List<PredictRecord>();
|
||||
public List<PredictTip> Tips = new List<PredictTip>();
|
||||
/// <summary>按盘口类型的历史:开过几个、开盘价之和、实际发生几次。玩家据此看出哪类盘口系统性地定价偏高或偏低。</summary>
|
||||
public Dictionary<string, PredictStat> Stats = new Dictionary<string, PredictStat>();
|
||||
public int Seq;
|
||||
/// <summary>每晚观测:当天新出现的事件标识(和 "F:派系")。窗口里缺任何一天的观测,盘口作废退款。</summary>
|
||||
public Dictionary<int, List<string>> Started = new Dictionary<int, List<string>>();
|
||||
public List<string> Prev;
|
||||
|
||||
public PredictMarket Find(int id) => Markets.Find(m => m.Id == id);
|
||||
public PredictPos PosOf(int id, string wallet) => Positions.Find(p => p.Market == id && p.Wallet == wallet);
|
||||
public List<PredictPos> PosAll(int id) => Positions.Where(p => p.Market == id).ToList();
|
||||
|
||||
private static double Share(Wallet acct, double amount, Func<string, double> price)
|
||||
{
|
||||
double total = acct.Value(price);
|
||||
return total > 0 ? Math.Min(1, amount * price(Assets.CRC) / total) : 0;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 买入:花 spend(含手续费)的 CRC。污点与成本按花掉的价值比例随资金进持仓。insider:这笔单下单时玩家已经知道答案(传闻纸条、派系特权)。
|
||||
/// </summary>
|
||||
public PredictResult Buy(Wallet acct, PredictMarket m, bool yes, double spend, int day, Func<string, double> pr, bool insider, out double shares)
|
||||
{
|
||||
shares = 0;
|
||||
if (!m.IsOpen(day)) return PredictResult.Closed;
|
||||
if (spend <= 0) return PredictResult.Amount;
|
||||
if (acct.Avail(Assets.CRC) + 1e-9 < spend) return PredictResult.Funds;
|
||||
var all = PosAll(m.Id);
|
||||
if (all.Any(x => x.Yes != yes)) return PredictResult.Opposite;
|
||||
var pos = PosOf(m.Id, acct.Address);
|
||||
double cost = spend / (1 + Tuning.PredictFee);
|
||||
shares = m.SharesFor(yes, cost);
|
||||
if (all.Sum(x => x.Shares) + shares > m.ShareCap + 1e-9) { shares = 0; return PredictResult.Cap; }
|
||||
double share = Share(acct, spend, pr);
|
||||
double taint = acct.Taint * share, basis = acct.Basis * share;
|
||||
acct.Add(Assets.CRC, -spend); acct.Taint -= taint; acct.Basis -= basis;
|
||||
if (yes) m.QYes += shares; else m.QNo += shares;
|
||||
if (pos == null) Positions.Add(pos = new PredictPos { Market = m.Id, Yes = yes, Wallet = acct.Address });
|
||||
pos.Shares += shares; pos.Cost += cost; pos.Taint += taint; pos.Basis += basis;
|
||||
if (insider) pos.Insider += shares;
|
||||
return PredictResult.Ok;
|
||||
}
|
||||
|
||||
/// <summary>全部卖出这个钱包在盘口里的持仓(盘口关闭前):收回 LMSR 的卖价减手续费,污点按比例退回,赚的部分是干净的。返回收回的 CRC。</summary>
|
||||
public PredictResult SellAll(Wallet acct, PredictMarket m, int day, out double got) => SellAll(acct, m, day, null, out got, out _);
|
||||
|
||||
/// <summary>
|
||||
/// 全部卖出;内幕持仓(这个盘口合计)达到查处线、而且卖出有赚,按查处概率被查:本金和收益全部没收,收益的一半记罪证(fraud > 0)。
|
||||
/// 先买后卖、赶在结算前离场,同样会被查。
|
||||
/// </summary>
|
||||
public PredictResult SellAll(Wallet acct, PredictMarket m, int day, Rng rng, out double got, out double fraud)
|
||||
{
|
||||
got = 0; fraud = 0;
|
||||
var pos = PosOf(m.Id, acct.Address);
|
||||
if (pos == null) return PredictResult.NoPosition;
|
||||
if (!m.IsOpen(day)) return PredictResult.Closed;
|
||||
double value = m.SellValue(pos.Yes, pos.Shares);
|
||||
got = value * (1 - Tuning.PredictFee);
|
||||
bool insider = PosAll(m.Id).Sum(x => x.Insider) >= Tuning.PredictInsiderShare * m.ShareCap;
|
||||
if (pos.Yes) m.QYes -= pos.Shares; else m.QNo -= pos.Shares;
|
||||
Positions.Remove(pos);
|
||||
if (rng != null && insider && pos.Insider > 0 && got > pos.Cost && rng.Chance(Math.Min(1, Tuning.PredictInsiderCatch * StoryMods.Current.Enforce(day))))
|
||||
{
|
||||
fraud = Math.Min(Tuning.PredictFraudCap, (got - pos.Cost) * Tuning.PredictFraudShare);
|
||||
got = 0;
|
||||
}
|
||||
Pay(acct, pos, got);
|
||||
return PredictResult.Ok;
|
||||
}
|
||||
|
||||
private static void Pay(Wallet acct, PredictPos pos, double payout)
|
||||
{
|
||||
double keep = pos.Cost > 0 ? Math.Min(1, payout / pos.Cost) : 0;
|
||||
acct.Add(Assets.CRC, payout); acct.Taint += pos.Taint * keep; acct.Basis += pos.Basis * keep;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 夜间:先登记今晚的观测,再结算 ToDay 到了的盘口(赢的钱回到下注的钱包,wallet 按地址找)。outcome 由接入层给出(事件 / 派系读观测,纯度和行情读游戏数值),null 表示拿不到数据。
|
||||
/// 赢家每份兑付 1 信用点;内幕持仓达到份额上限的 <see cref="Tuning.PredictInsiderShare"/> 后,有概率被查:本金和收益全部没收,收益的一半记罪证。
|
||||
/// </summary>
|
||||
public List<PredictEvent> Night(int day, IEnumerable<string> activeNow, Func<PredictMarket, bool?> outcome, Func<string, Wallet> wallet, Rng rng, double push = 0)
|
||||
{
|
||||
var now = activeNow.Distinct().ToList();
|
||||
if (Prev != null) Started[day] = now.Where(x => !Prev.Contains(x)).ToList();
|
||||
Prev = now;
|
||||
foreach (var k in Started.Keys.Where(k => k < day - 12).ToList()) Started.Remove(k);
|
||||
var evs = new List<PredictEvent>();
|
||||
foreach (var m in Markets.Where(x => x.Outcome < 0 && x.ToDay <= day).ToList())
|
||||
{
|
||||
bool? res = outcome(m);
|
||||
var all = PosAll(m.Id);
|
||||
foreach (var pos in all) Positions.Remove(pos);
|
||||
double cost = all.Sum(x => x.Cost);
|
||||
if (res == null)
|
||||
{
|
||||
m.Outcome = 2;
|
||||
foreach (var pos in all) Pay(wallet(pos.Wallet), pos, pos.Cost);
|
||||
if (all.Count > 0) evs.Add(new PredictEvent { Kind = "void", Title = m.Title, Market = m, Amount = cost });
|
||||
Record(day, m, 2, 0, all.Count > 0);
|
||||
continue;
|
||||
}
|
||||
m.Outcome = res.Value ? 1 : 0;
|
||||
string sk = m.Kind.ToString();
|
||||
if (!Stats.TryGetValue(sk, out var st)) Stats[sk] = st = new PredictStat();
|
||||
st.Count++; st.SumP0 += m.P0; if (res.Value) st.Hits++;
|
||||
var winners = all.Where(x => x.Yes == res.Value).ToList();
|
||||
// 操纵:行情盘上,赢家的方向和玩家推价的方向一致时按推价幅度被查——本金和收益都没收,收益的一半记罪证
|
||||
if (m.Kind == PredictKind.Price && winners.Count > 0 && winners.Any(x => x.Yes ? push > 0 : push < 0) && rng.Chance(Math.Min(1, Market.ManipChance(push) * StoryMods.Current.Enforce(day))))
|
||||
{
|
||||
double profitM = winners.Sum(x => x.Shares) - cost;
|
||||
evs.Add(new PredictEvent { Kind = "manip", Title = m.Title, Market = m, Amount = cost, Fraud = Math.Min(Tuning.PredictFraudCap, Math.Max(0, profitM) * Tuning.PredictFraudShare) });
|
||||
Record(day, m, m.Outcome, -cost, true);
|
||||
continue;
|
||||
}
|
||||
if (all.Count > 0 && winners.Count == 0)
|
||||
{
|
||||
evs.Add(new PredictEvent { Kind = "lose", Title = m.Title, Market = m, Amount = cost });
|
||||
Record(day, m, m.Outcome, -cost, true);
|
||||
}
|
||||
else if (winners.Count > 0)
|
||||
{
|
||||
double payout = winners.Sum(x => x.Shares), profit = payout - cost;
|
||||
// 内幕持仓按盘口合计(拆到几个钱包里也一样)
|
||||
if (all.Sum(x => x.Insider) >= Tuning.PredictInsiderShare * m.ShareCap && rng.Chance(Math.Min(1, Tuning.PredictInsiderCatch * StoryMods.Current.Enforce(day))))
|
||||
{
|
||||
// 查实:本金和收益全部没收
|
||||
evs.Add(new PredictEvent { Kind = "caught", Title = m.Title, Market = m, Amount = payout, Fraud = Math.Min(Tuning.PredictFraudCap, Math.Max(0, profit) * Tuning.PredictFraudShare) });
|
||||
Record(day, m, m.Outcome, -cost, true);
|
||||
}
|
||||
else
|
||||
{
|
||||
foreach (var pos in winners) Pay(wallet(pos.Wallet), pos, pos.Shares);
|
||||
evs.Add(new PredictEvent { Kind = "win", Title = m.Title, Market = m, Amount = payout });
|
||||
Record(day, m, m.Outcome, profit, true);
|
||||
}
|
||||
}
|
||||
else Record(day, m, m.Outcome, 0, false);
|
||||
}
|
||||
Markets.RemoveAll(m => m.Outcome >= 0);
|
||||
Tips.RemoveAll(t => Find(t.Market) == null);
|
||||
return evs;
|
||||
}
|
||||
|
||||
private void Record(int day, PredictMarket m, int outcome, double pnl, bool held)
|
||||
{
|
||||
Recent.Add(new PredictRecord { Day = day, Title = m.Title, Outcome = outcome, Pnl = pnl, Held = held });
|
||||
while (Recent.Count > Tuning.PredictHistory) Recent.RemoveAt(0);
|
||||
}
|
||||
|
||||
public PredictTip TipFor(int market) => Tips.Find(t => t.Market == market);
|
||||
|
||||
/// <summary>造一条内幕消息:假情报(概率 IntelFake)说的与真相相反,否则按这一档的准确率说对或说错。</summary>
|
||||
public static PredictTip MakeTip(PredictMarket m, bool truth, int tier, Rng rng)
|
||||
{
|
||||
bool claim;
|
||||
if (rng.Chance(Tuning.IntelFake)) claim = !truth;
|
||||
else claim = rng.Chance(Tuning.IntelTipAcc[tier]) ? truth : !truth;
|
||||
return new PredictTip { Market = m.Id, Tier = tier, Claim = claim, Paid = Tuning.IntelTipPrice[tier] * m.Loss };
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 夜间的消息反应:还能交易的盘口(明天仍开着)向"公开信息下的合理概率"靠拢 PredictDrift,再加 logit 噪声(NPC 流量)。
|
||||
/// 价格在夜里才反应,所以白天先看到报纸、传闻的人可以抢在前面买、等涨价再卖。target 返回 null 表示这个盘口没有新信息。
|
||||
/// </summary>
|
||||
public List<PredictMove> Drift(int day, Func<PredictMarket, double?> target, Rng rng)
|
||||
{
|
||||
var moves = new List<PredictMove>();
|
||||
foreach (var m in Markets.Where(x => x.Outcome < 0 && x.FromDay > day + 1))
|
||||
{
|
||||
m.PrevP = m.PYes;
|
||||
double p = m.PYes, t = target(m) ?? p;
|
||||
t = Math.Max(Tuning.PredictPMin, Math.Min(Tuning.PredictPMax, t));
|
||||
double pt = p + Tuning.PredictDrift * (t - p);
|
||||
double lp = Math.Log(pt / (1 - pt)) + Tuning.PredictNoise * rng.Gauss();
|
||||
pt = Math.Max(Tuning.PredictPMin, Math.Min(Tuning.PredictPMax, 1 / (1 + Math.Exp(-lp))));
|
||||
m.QYes = m.QNo + m.B * Math.Log(pt / (1 - pt));
|
||||
moves.Add(new PredictMove { Market = m, From = m.PrevP, To = m.PYes });
|
||||
}
|
||||
return moves;
|
||||
}
|
||||
|
||||
/// <summary>读观测:窗口里每一天都有记录才能判断;有任何一天缺就返回 null(作废)。</summary>
|
||||
public bool? Happened(PredictMarket m)
|
||||
{
|
||||
string tag = m.Kind == PredictKind.Faction ? "F:" + m.Key : m.Key;
|
||||
bool any = false;
|
||||
for (int d = m.FromDay; d <= m.ToDay; d++)
|
||||
{
|
||||
if (!Started.TryGetValue(d, out var list)) return null;
|
||||
if (list.Contains(tag)) any = true;
|
||||
}
|
||||
return any;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 每天开门后补盘:开放的盘口少于下限时补到下限,之后每天再随机新开一两个,总数不超过上限。同类同键的盘口不重复开。
|
||||
/// 返回新开的盘口。
|
||||
/// </summary>
|
||||
public List<PredictMarket> Refill(int day, Rng rng, IList<PredictCandidate> candidates)
|
||||
{
|
||||
var made = new List<PredictMarket>();
|
||||
int open = Markets.Count(m => m.Outcome < 0);
|
||||
int want = open < Tuning.PredictOpenMin ? Tuning.PredictOpenMin - open : 0;
|
||||
want = Math.Max(want, rng.Range(1, Tuning.PredictNewPerDay));
|
||||
want = Math.Min(want, Tuning.PredictOpenMax - open);
|
||||
var pool = candidates.Where(c => !Markets.Any(m => m.Outcome < 0 && m.Kind == c.Kind && m.Key == c.Key)).ToList();
|
||||
while (want-- > 0 && pool.Count > 0)
|
||||
{
|
||||
var c = pool[rng.Range(0, pool.Count - 1)];
|
||||
pool.RemoveAll(x => x.Kind == c.Kind && x.Key == c.Key);
|
||||
int from = c.Tomorrow ? day + 1 : day + 1 + rng.Range(0, 2);
|
||||
int to = c.Tomorrow ? from : from + rng.Range(0, 2);
|
||||
var m = PredictMarket.Create(++Seq, c.Kind, c.Key, c.Title, c.Param, day, from, to, c.Prob(from, to));
|
||||
Markets.Add(m); made.Add(m);
|
||||
}
|
||||
return made;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>盘口先验概率:事件按游戏的掷骰规则,纯度按均匀分布,行情按本 mod 的价格过程。</summary>
|
||||
public static class PredictMath
|
||||
{
|
||||
/// <summary>某个常规事件在窗口里出现的概率:每天先过"有事件"这一关(chance),再按权重在可选事件里抽中。</summary>
|
||||
public static double EventProb(double dayChance, double odd, double totalOdd, int days)
|
||||
{
|
||||
double p1 = totalOdd > 0 ? dayChance * odd / totalOdd : 0;
|
||||
return 1 - Math.Pow(1 - p1, days);
|
||||
}
|
||||
|
||||
/// <summary>某天 gas 不低于阈值的概率(已知相位):周期值 × (1 ± 噪声) 均匀分布。</summary>
|
||||
public static double GasAtLeast(int day, int phase, double threshold)
|
||||
{
|
||||
double c = TxRules.GasCycle(day, phase), hi = c * (1 + Tuning.TxGasNoise), lo = c * (1 - Tuning.TxGasNoise);
|
||||
return Math.Max(0, Math.Min(1, (hi - threshold) / (hi - lo)));
|
||||
}
|
||||
|
||||
/// <summary>不知道相位时的先验:七个相位等可能。</summary>
|
||||
public static double GasFlat(int day, double threshold)
|
||||
{
|
||||
double s = 0;
|
||||
for (int ph = 0; ph < Tuning.TxGasPeriod; ph++) s += GasAtLeast(day, ph, threshold);
|
||||
return s / Tuning.TxGasPeriod;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// CRA 预警在 [from, to] 夜里发出的概率:每晚补贴池先被消耗,归零那晚必发,否则按日概率;
|
||||
/// 窗口之前已经发出的不算(那就是"否")。subsidy / drain 是今天的补贴池和每晚消耗,today 是今晚。
|
||||
/// </summary>
|
||||
public static double CraWarnProb(double subsidy, double drain, int today, int from, int to, double dailyHazard)
|
||||
{
|
||||
double noWarn = 1, inWindow = 0;
|
||||
for (int d = today; d <= to; d++)
|
||||
{
|
||||
subsidy -= drain;
|
||||
double h = subsidy <= 0 ? 1 : dailyHazard;
|
||||
if (d >= from) inWindow += noWarn * h;
|
||||
noWarn *= 1 - h;
|
||||
}
|
||||
return inWindow;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 矿机时代在 [from, to] 开始的概率:没出预警时在 [eraMin, eraMax] 里均匀;预警已出(warnDay >= 0)时落在预警后 EraWarnMin..EraWarnMax 天。
|
||||
/// 只算还没过去的日子(today 之后)。
|
||||
/// </summary>
|
||||
public static double EraProb(int today, int from, int to, int warnDay)
|
||||
{
|
||||
int lo = warnDay >= 0 ? warnDay + Tuning.EraWarnMin : Tuning.EraMin, hi = warnDay >= 0 ? warnDay + Tuning.EraWarnMax : Tuning.EraMax;
|
||||
lo = Math.Max(lo, today + 1);
|
||||
if (hi < lo) return 0;
|
||||
int a = Math.Max(lo, from), b = Math.Min(hi, to);
|
||||
return b < a ? 0 : (b - a + 1) / (double)(hi - lo + 1);
|
||||
}
|
||||
|
||||
public static double FactionProb(int days) => 1 - Math.Pow(1 - Tuning.PredictFactionDaily, days);
|
||||
|
||||
/// <summary>均匀整数 lo..hi 里不低于 threshold 的概率。</summary>
|
||||
public static double PurityAtLeast(double threshold, int lo, int hi)
|
||||
{
|
||||
double n = hi - lo + 1, k = hi - Math.Ceiling(threshold) + 1;
|
||||
return Math.Max(0, Math.Min(1, k / n));
|
||||
}
|
||||
|
||||
public static double Phi(double x)
|
||||
{
|
||||
double t = 1 / (1 + 0.2316419 * Math.Abs(x));
|
||||
double d = 0.3989423 * Math.Exp(-x * x / 2);
|
||||
double p = d * t * (0.3193815 + t * (-0.3565638 + t * (1.781478 + t * (-1.821256 + t * 1.330274))));
|
||||
return x > 0 ? 1 - p : p;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 价格在 nights 个夜晚之后(每晚向锚回归 revert、加 vol 的对数噪声,每个早上再加 vol/2 的开门波动)不低于 threshold 的概率。
|
||||
/// 对数价格近似正态;锚按今天的值外推(事件和减半的变化不计)。
|
||||
/// </summary>
|
||||
public static double PriceAtLeast(double price, double anchor, double vol, double revert, int nights, double threshold)
|
||||
{
|
||||
double m = Math.Log(price), la = Math.Log(anchor), v = 0;
|
||||
for (int i = 0; i < nights; i++)
|
||||
{
|
||||
m += revert * (la - m);
|
||||
v = (1 - revert) * (1 - revert) * v + vol * vol + vol * vol / 4;
|
||||
}
|
||||
double sd = Math.Sqrt(Math.Max(v, 1e-12));
|
||||
return 1 - Phi((Math.Log(threshold) - m) / sd);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -9,7 +9,7 @@ namespace Decentralized.Domain
|
||||
public static class RigSlots
|
||||
{
|
||||
public const int Base = 2, Max = 5;
|
||||
public const int CellWidth = 2, CellsPerSlot = 2;
|
||||
public const int CellWidth = 3, CellsPerSlot = 2;
|
||||
|
||||
/// <summary>升级到第 n 个槽需要的电子元件(物品 id,件数)。n 从 3 开始。</summary>
|
||||
public static (string Item, int Count) Cost(int slot)
|
||||
@@ -45,7 +45,7 @@ namespace Decentralized.Domain
|
||||
return take;
|
||||
}
|
||||
|
||||
/// <summary>显卡格子的形状字符串:宽 2,高 2 × 最大槽数;前 slots × 2 行可放(0),其余不可放(1)。</summary>
|
||||
/// <summary>显卡格子的形状字符串:宽 3(一张卡 3×2 格),高 2 × 最大槽数;前 slots × 2 行可放(0),其余不可放(1)。</summary>
|
||||
public static string Shape(int slots)
|
||||
{
|
||||
var sb = new System.Text.StringBuilder();
|
||||
|
||||
@@ -0,0 +1,26 @@
|
||||
using System;
|
||||
|
||||
namespace Decentralized.Domain
|
||||
{
|
||||
/// <summary>mod 设置里的倍率(全局,不随存档)。接入层读设置后写进来;领域层在对应概率和产出处乘上。</summary>
|
||||
public static class Scales
|
||||
{
|
||||
/// <summary>风险倍率:骗局、跑路、钱包投毒、地址劫持、钓鱼的发生概率。</summary>
|
||||
public static double Risk = 1;
|
||||
/// <summary>挖矿产出倍率:玩家矿机拿到的区块奖励。</summary>
|
||||
public static double Mining = 1;
|
||||
|
||||
/// <summary>概率乘风险倍率,封顶 1。</summary>
|
||||
public static double R(double chance) => Math.Min(1, chance * Risk);
|
||||
|
||||
/// <summary>设置里的倍率档位(“×1.5”)。</summary>
|
||||
public static readonly string[] Choices = { "×0.5", "×1", "×1.5", "×2" };
|
||||
public const string Default = "×1";
|
||||
|
||||
public static double Parse(string s)
|
||||
{
|
||||
if (s != null && s.StartsWith("×") && double.TryParse(s.Substring(1), System.Globalization.NumberStyles.Float, System.Globalization.CultureInfo.InvariantCulture, out var v) && v >= 0) return v;
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,237 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
|
||||
namespace Decentralized.Domain
|
||||
{
|
||||
/// <summary>空投:签名领取。正规空投不要授权或只要有限授权,给一点币;钓鱼空投要求对某个币"无上限授权",几晚后把这个钱包里的这种币转走。</summary>
|
||||
public sealed class Airdrop
|
||||
{
|
||||
public int Id, Expire;
|
||||
public string Name, Asset;
|
||||
/// <summary>领取要授权的额度:0 = 不要授权;double.PositiveInfinity = 无上限。</summary>
|
||||
public double Approve;
|
||||
public double Reward;
|
||||
public bool Scam, Claimed;
|
||||
/// <summary>已为这个空投授权的钱包地址(签过授权合约);空 = 还没授权。领取要用授权过的钱包。</summary>
|
||||
public string AuthWallet;
|
||||
}
|
||||
|
||||
/// <summary>钱包对某个合约的授权。钓鱼授权到 DrainDay 那晚把这种币转走,撤销后作废。</summary>
|
||||
public sealed class Approval
|
||||
{
|
||||
public int Id, DrainDay = -1;
|
||||
public string Wallet, Asset, Spender;
|
||||
public double Limit;
|
||||
public bool Scam;
|
||||
}
|
||||
|
||||
/// <summary>第三方收益池(CRC):日息、储备、有没有时间锁、有没有审计都看得见;是不是骗局看不见,跑路时存款全部没了。</summary>
|
||||
public sealed class YieldPool
|
||||
{
|
||||
public int Id, OpenDay;
|
||||
public string Name;
|
||||
public double Rate, Reserve, Cap;
|
||||
public bool Timelock, Audited, Scam, Closed;
|
||||
public Dictionary<string, double> Deposits = new Dictionary<string, double>();
|
||||
public Dictionary<string, double> Taint = new Dictionary<string, double>(), Basis = new Dictionary<string, double>();
|
||||
/// <summary>时间锁池子的取款队列:钱包 → (到账日, 数额)。</summary>
|
||||
public List<YieldWithdraw> Pending = new List<YieldWithdraw>();
|
||||
public double Total => Deposits.Values.Sum();
|
||||
public double Of(string wallet) => Deposits.TryGetValue(wallet, out var v) ? v : 0;
|
||||
}
|
||||
|
||||
public sealed class YieldWithdraw { public string Wallet; public int Day; public double Amount, Taint, Basis; }
|
||||
|
||||
/// <summary>夜间发生的事。Kind:drain(钓鱼授权转走)/ rug(收益池跑路)/ dry(正规池储备耗尽,退本金)/ paid(取款到账)/ wickback(插针回去了)。</summary>
|
||||
public sealed class ScamEvent
|
||||
{
|
||||
public string Kind, Name, Wallet, Asset;
|
||||
public double Amount;
|
||||
}
|
||||
|
||||
/// <summary>NPC 骗局:空投与授权、第三方收益池。插针在 <see cref="Market"/> 里。</summary>
|
||||
public sealed class Scams
|
||||
{
|
||||
public List<Airdrop> Airdrops = new List<Airdrop>();
|
||||
public List<Approval> Approvals = new List<Approval>();
|
||||
public List<YieldPool> Pools = new List<YieldPool>();
|
||||
public int Seq;
|
||||
/// <summary>骗子用过的收款地址(假客服、钓鱼):转到这些地址时晨间日志说明被骗。</summary>
|
||||
public List<string> ScamAddrs = new List<string>();
|
||||
|
||||
private static readonly string[] AirdropNames = { "Poinbase", "PSC Foundation", "RatDigg", "Revolution DAO", "Gutter Labs", "Station Rewards" };
|
||||
private static readonly string[] PoolNames = { "Nebula Yield", "Rustwater Vault", "Orbit Farm", "Deck 9 Savings", "Gutterflow Pool", "Halo Staking", "Ironclad Earn" };
|
||||
|
||||
public static double ScamChance(double rate, bool timelock, bool audited)
|
||||
{
|
||||
int i = Array.IndexOf(Tuning.YieldRates, rate);
|
||||
double p = i >= 0 ? Tuning.YieldScamByRate[i] : 0.5;
|
||||
if (timelock) p -= Tuning.YieldScamTimelock;
|
||||
if (audited) p -= Tuning.YieldScamAudit;
|
||||
return Math.Max(0.02, Math.Min(0.95, p));
|
||||
}
|
||||
|
||||
// ——— 空投 ———
|
||||
|
||||
/// <summary>新空投。钓鱼的名字常是正规名字的仿冒(一个字符不同),要求对一种币无上限授权,奖励看起来更高。</summary>
|
||||
public Airdrop NewAirdrop(int day, Rng rng, string[] assets)
|
||||
{
|
||||
bool scam = rng.Chance(Scales.R(Tuning.AirdropScam));
|
||||
string name = AirdropNames[rng.Range(0, AirdropNames.Length - 1)];
|
||||
if (scam && rng.Chance(0.6)) name = Typo(name, rng);
|
||||
string asset = assets[rng.Range(0, assets.Length - 1)];
|
||||
double reward = Math.Round(rng.Range(Tuning.AirdropRewardMin, Tuning.AirdropRewardMax));
|
||||
if (scam) reward = Math.Round(reward * rng.Range(1.5, 3.0));
|
||||
// 钓鱼:多数要无上限授权,三成要一个看着像有限、其实远大于奖励的额度
|
||||
double approve = scam ? (rng.Chance(0.3) ? Math.Round(reward * rng.Range(20.0, 100.0) / 10) * 10 : double.PositiveInfinity) : rng.Chance(0.5) ? 0 : Math.Round(rng.Range(10.0, 60.0));
|
||||
var a = new Airdrop { Id = ++Seq, Name = name, Asset = asset, Approve = approve, Reward = reward, Scam = scam, Expire = day + Tuning.AirdropDays };
|
||||
Airdrops.Add(a);
|
||||
return a;
|
||||
}
|
||||
|
||||
private static string Typo(string s, Rng rng)
|
||||
{
|
||||
var swaps = new Dictionary<char, char> { ['o'] = '0', ['i'] = '1', ['l'] = '1', ['e'] = '3', ['a'] = '4', ['s'] = '5', ['n'] = 'm' };
|
||||
var idx = Enumerable.Range(0, s.Length).Where(i => swaps.ContainsKey(char.ToLowerInvariant(s[i]))).ToList();
|
||||
if (idx.Count == 0) return s + "s";
|
||||
int k = idx[rng.Range(0, idx.Count - 1)];
|
||||
return s.Substring(0, k) + swaps[char.ToLowerInvariant(s[k])] + s.Substring(k + 1);
|
||||
}
|
||||
|
||||
/// <summary>这个钱包是否已为这个空投授权。</summary>
|
||||
public static bool Authorized(Airdrop a, Wallet w) => a != null && w != null && !string.IsNullOrEmpty(a.AuthWallet) && ChainAddress.Same(a.AuthWallet, w.Address);
|
||||
|
||||
/// <summary>为空投授权钱包(签完授权合约后调用);换了钱包要重新授权。</summary>
|
||||
public static bool Authorize(Airdrop a, Wallet w, int day)
|
||||
{
|
||||
if (a == null || w == null || a.Claimed || day > a.Expire) return false;
|
||||
a.AuthWallet = w.Address;
|
||||
return true;
|
||||
}
|
||||
|
||||
/// <summary>领取:正规空投给奖励(干净的 CRC),钓鱼空投给一点点诱饵;有授权的记一条授权,钓鱼授权定下转走的那晚。</summary>
|
||||
public Approval Claim(Airdrop a, Wallet w, int day, Rng rng, out double got)
|
||||
{
|
||||
got = 0;
|
||||
if (a.Claimed || day > a.Expire) return null;
|
||||
a.Claimed = true;
|
||||
got = a.Scam ? Math.Round(a.Reward * 0.05, 2) : a.Reward;
|
||||
w.Add(Assets.CRC, got); w.Basis += got;
|
||||
if (a.Approve <= 0) return null;
|
||||
var ap = new Approval { Id = ++Seq, Wallet = w.Address, Asset = a.Asset, Spender = a.Name, Limit = a.Approve, Scam = a.Scam, DrainDay = a.Scam ? day + rng.Range(Tuning.AirdropDrainMin, Tuning.AirdropDrainMax) : -1 };
|
||||
Approvals.Add(ap);
|
||||
return ap;
|
||||
}
|
||||
|
||||
public bool Revoke(int id) => Approvals.RemoveAll(x => x.Id == id) > 0;
|
||||
|
||||
// ——— 收益池 ———
|
||||
|
||||
public YieldPool NewPool(int day, Rng rng)
|
||||
{
|
||||
double rate = Tuning.YieldRates[rng.Range(0, Tuning.YieldRates.Length - 1)];
|
||||
bool timelock = rng.Chance(0.5), audited = rng.Chance(0.4);
|
||||
bool scam = rng.Chance(ScamChance(rate, timelock, audited));
|
||||
double cap = Tuning.YieldCap0 + Tuning.YieldCapPerDay * day;
|
||||
var used = Pools.Where(p => !p.Closed).Select(p => p.Name).ToList();
|
||||
var names = PoolNames.Where(n => !used.Contains(n)).ToList();
|
||||
var p2 = new YieldPool
|
||||
{
|
||||
Id = ++Seq, OpenDay = day, Name = names.Count > 0 ? names[rng.Range(0, names.Count - 1)] : "Pool " + Seq,
|
||||
Rate = rate, Timelock = timelock, Audited = audited, Scam = scam, Cap = cap,
|
||||
// 正规池的储备够付若干天满额利息;骗局池报一个好看的数字(不会真付到那么多天,跑路前一直照付)
|
||||
Reserve = Math.Round(rate * cap * Tuning.YieldReserveDays * (scam ? rng.Range(0.8, 1.6) : rng.Range(0.6, 1.2))),
|
||||
};
|
||||
Pools.Add(p2);
|
||||
return p2;
|
||||
}
|
||||
|
||||
public bool Deposit(YieldPool p, Wallet w, double amount, Func<string, double> pr)
|
||||
{
|
||||
if (p.Closed || amount <= 0 || w.Avail(Assets.CRC) + 1e-9 < amount || p.Total + amount > p.Cap + 1e-9) return false;
|
||||
double total = w.Value(pr), share = total > 0 ? Math.Min(1, amount * pr(Assets.CRC) / total) : 0;
|
||||
double taint = w.Taint * share, basis = w.Basis * share;
|
||||
w.Add(Assets.CRC, -amount); w.Taint -= taint; w.Basis -= basis;
|
||||
p.Deposits[w.Address] = p.Of(w.Address) + amount;
|
||||
p.Taint[w.Address] = (p.Taint.TryGetValue(w.Address, out var t) ? t : 0) + taint;
|
||||
p.Basis[w.Address] = (p.Basis.TryGetValue(w.Address, out var b) ? b : 0) + basis;
|
||||
return true;
|
||||
}
|
||||
|
||||
/// <summary>取出:没有时间锁的马上到账;有时间锁的进队列,几天后到账(跑路了就没了)。返回马上到账的数额。</summary>
|
||||
public double Withdraw(YieldPool p, Wallet w, int day)
|
||||
{
|
||||
double amt = p.Of(w.Address);
|
||||
if (amt <= 0 || p.Closed) return 0;
|
||||
double taint = p.Taint.TryGetValue(w.Address, out var t) ? t : 0, basis = p.Basis.TryGetValue(w.Address, out var b) ? b : 0;
|
||||
p.Deposits.Remove(w.Address); p.Taint.Remove(w.Address); p.Basis.Remove(w.Address);
|
||||
if (p.Timelock) { p.Pending.Add(new YieldWithdraw { Wallet = w.Address, Day = day + Tuning.YieldLockDays, Amount = amt, Taint = taint, Basis = basis }); return 0; }
|
||||
Pay(w, amt, taint, basis);
|
||||
return amt;
|
||||
}
|
||||
|
||||
private static void Pay(Wallet w, double amt, double taint, double basis)
|
||||
{
|
||||
w.Add(Assets.CRC, amt); w.Taint += taint; w.Basis += basis;
|
||||
}
|
||||
|
||||
// ——— 夜间 ———
|
||||
|
||||
/// <summary>
|
||||
/// 夜间:钓鱼授权到期转走;收益池计息、储备耗尽的正规池退本金关闭、骗局池按概率跑路;时间锁取款到账;过期空投清掉;随机新空投和新收益池。
|
||||
/// </summary>
|
||||
public List<ScamEvent> Night(int day, Rng rng, Func<string, Wallet> own, string[] airdropAssets, Func<string, double> pr = null)
|
||||
{
|
||||
var evs = new List<ScamEvent>();
|
||||
foreach (var ap in Approvals.Where(x => x.Scam && x.DrainDay >= 0 && x.DrainDay <= day).ToList())
|
||||
{
|
||||
Approvals.Remove(ap);
|
||||
var w = own(ap.Wallet);
|
||||
if (w == null) continue;
|
||||
double amt = Math.Min(ap.Limit, w.Avail(ap.Asset));
|
||||
if (amt <= 1e-9) continue;
|
||||
if (pr != null) w.Spend(ap.Asset, amt, pr); else w.Add(ap.Asset, -amt);
|
||||
evs.Add(new ScamEvent { Kind = "drain", Name = ap.Spender, Wallet = ap.Wallet, Asset = ap.Asset, Amount = amt });
|
||||
}
|
||||
foreach (var p in Pools.Where(x => !x.Closed).ToList())
|
||||
{
|
||||
if (p.Scam && p.Total > 0 && day > p.OpenDay && rng.Chance(Scales.R(Tuning.YieldRugNightly)))
|
||||
{
|
||||
foreach (var kv in p.Deposits) evs.Add(new ScamEvent { Kind = "rug", Name = p.Name, Wallet = kv.Key, Asset = Assets.CRC, Amount = kv.Value });
|
||||
foreach (var q in p.Pending) evs.Add(new ScamEvent { Kind = "rug", Name = p.Name, Wallet = q.Wallet, Asset = Assets.CRC, Amount = q.Amount });
|
||||
p.Deposits.Clear(); p.Pending.Clear(); p.Closed = true;
|
||||
continue;
|
||||
}
|
||||
double interest = p.Total * p.Rate;
|
||||
if (!p.Scam && interest > p.Reserve)
|
||||
{
|
||||
foreach (var kv in p.Deposits.ToList())
|
||||
{
|
||||
var w = own(kv.Key);
|
||||
if (w != null) Pay(w, kv.Value, p.Taint.TryGetValue(kv.Key, out var t) ? t : 0, p.Basis.TryGetValue(kv.Key, out var b) ? b : 0);
|
||||
evs.Add(new ScamEvent { Kind = "dry", Name = p.Name, Wallet = kv.Key, Asset = Assets.CRC, Amount = kv.Value });
|
||||
}
|
||||
p.Deposits.Clear(); p.Closed = true;
|
||||
}
|
||||
else
|
||||
{
|
||||
p.Reserve -= interest;
|
||||
foreach (var k in p.Deposits.Keys.ToList()) p.Deposits[k] *= 1 + p.Rate;
|
||||
}
|
||||
foreach (var q in p.Pending.Where(x => x.Day <= day).ToList())
|
||||
{
|
||||
p.Pending.Remove(q);
|
||||
var w = own(q.Wallet);
|
||||
if (w != null) Pay(w, q.Amount, q.Taint, q.Basis);
|
||||
evs.Add(new ScamEvent { Kind = "paid", Name = p.Name, Wallet = q.Wallet, Asset = Assets.CRC, Amount = q.Amount });
|
||||
}
|
||||
}
|
||||
Pools.RemoveAll(p => p.Closed && p.Pending.Count == 0 && day - p.OpenDay > 20);
|
||||
Airdrops.RemoveAll(a => a.Expire < day + 1);
|
||||
if (rng.Chance(Tuning.AirdropChance)) NewAirdrop(day + 1, rng, airdropAssets);
|
||||
if (Pools.Count(p => !p.Closed) < Tuning.YieldPoolMax && rng.Chance(Tuning.YieldPoolChance)) NewPool(day + 1, rng);
|
||||
return evs;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,20 +1,46 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
|
||||
namespace Decentralized.Domain
|
||||
{
|
||||
/// <summary>
|
||||
/// 三种稳定币的价格与状态:CRC(上层,托管银行出事时脱锚、可能减记),CRT(黑市,镇压或火并时脱锚,
|
||||
/// 镇压期间按黑市声望出卖客户),CRA(革命军,质押付息,补贴池告急或外生触发时进入三天死亡螺旋)。
|
||||
/// 镇压期间按黑市声望出卖客户),CRA(革命军,部分抵押:流通量 S、储备 R(CRC)、抵押率 c;质押利息以无抵押的新 CRA 付出,
|
||||
/// 稀释储备覆盖率 R/S;革命军挪用储备时 R/S 低于崩盘线进入三天死亡螺旋,劫掠上层补回储备)。
|
||||
/// </summary>
|
||||
public enum CraOrderKind { Minted, Burned, Lost }
|
||||
|
||||
/// <summary>官方一级市场的排队单:铸造(存入 CRC 和 SPARK)或销毁(存入 CRA),到期结算,官方可能把它黑掉。</summary>
|
||||
public sealed class CraOrder
|
||||
{
|
||||
public int Id, Due;
|
||||
public string Wallet;
|
||||
public bool Mint;
|
||||
public double Cra, Crc, Spark, C;
|
||||
}
|
||||
|
||||
public sealed class CraOrderEvent
|
||||
{
|
||||
public CraOrder Order;
|
||||
public CraOrderKind Kind;
|
||||
public double Cra, Crc, Spark;
|
||||
}
|
||||
|
||||
public sealed class Stablecoins
|
||||
{
|
||||
public double Crc = 1, Crt = 1, Cra = 1;
|
||||
public int CrcDepegEnd = -1, CrtDepegEnd = -1;
|
||||
public bool CrcHaircutPending;
|
||||
public double CraSubsidy = Tuning.CraSubsidy0;
|
||||
public int CraWarnDay = -1, CraSpiralDay = -1;
|
||||
/// <summary>CRA 流通量与储备(CRC);c 是现在铸造要求的 CRC 份额(0~1)。</summary>
|
||||
public double Supply = Tuning.CraS0, Reserve = Tuning.CraS0 * Tuning.CraC0, C = Tuning.CraC0;
|
||||
/// <summary>预兆日(新闻发出的那天)、预定的挪用日、崩盘开始日(-1 = 没有)。</summary>
|
||||
public int CraWarnDay = -1, CraEventDay = -1, CraCrashDay = -1;
|
||||
public List<CraOrder> Orders = new List<CraOrder>();
|
||||
public int OrderSeq;
|
||||
public double RevPower = 50;
|
||||
/// <summary>平衡代币 SPARK 的价格(信用点);SparkPre 是螺旋开始前一刻的价格,螺旋三天按它的倍数走。</summary>
|
||||
public double Spark = Tuning.SparkStart, SparkPre = -1;
|
||||
public List<double> RevHistory = new List<double>();
|
||||
|
||||
public double Price(string asset)
|
||||
@@ -24,6 +50,7 @@ namespace Decentralized.Domain
|
||||
case Assets.CRC: return Crc;
|
||||
case Assets.CRT: return Crt;
|
||||
case Assets.CRA: return Cra;
|
||||
case Assets.SPARK: return Spark;
|
||||
default: return 1;
|
||||
}
|
||||
}
|
||||
@@ -31,34 +58,91 @@ namespace Decentralized.Domain
|
||||
/// <summary>减记发生时返回 CRC 持有量要乘的系数(其余情况为 1)。</summary>
|
||||
public double OnEventStart(MarketEvent ev, int day, Rng rng)
|
||||
{
|
||||
if (ev == MarketEvent.RevRaidUpper && CrcDepegEnd < 0 && rng.Chance(Tuning.CrcDepegChance))
|
||||
if (ev == MarketEvent.RevRaidUpper && CrcDepegEnd < 0 && rng.Chance(Tuning.CrcDepegChance * StoryMods.Current.CrcDepeg))
|
||||
{
|
||||
Crc = rng.Range(Tuning.CrcDepegMin, Tuning.CrcDepegMax);
|
||||
CrcDepegEnd = day + rng.Range(Tuning.CrcDepegDaysMin, Tuning.CrcDepegDaysMax);
|
||||
CrcHaircutPending = rng.Chance(Tuning.CrcHaircutChance);
|
||||
CrcHaircutPending = rng.Chance(Math.Min(1, Tuning.CrcHaircutChance * StoryMods.Current.CrcHaircut));
|
||||
}
|
||||
if ((ev == MarketEvent.GangWar || ev == MarketEvent.Crackdown) && CrtDepegEnd < 0 && rng.Chance(Tuning.CrtDepegChance))
|
||||
if ((ev == MarketEvent.GangWar || ev == MarketEvent.Crackdown) && CrtDepegEnd < 0 && rng.Chance(Tuning.CrtDepegChance * StoryMods.Current.CrtDepeg))
|
||||
{
|
||||
Crt = rng.Range(Tuning.CrtDepegMin, Tuning.CrtDepegMax);
|
||||
CrtDepegEnd = day + rng.Range(Tuning.CrtDepegDaysMin, Tuning.CrtDepegDaysMax);
|
||||
}
|
||||
if (ev == MarketEvent.RevRaidUpper) { Spark *= Tuning.SparkRaidShock; if (CraCrashDay < 0) Reserve += Tuning.CraLoot * Supply; }
|
||||
if (ev == MarketEvent.LowerUnrest) Spark *= Tuning.SparkUnrestShock;
|
||||
return 1;
|
||||
}
|
||||
|
||||
/// <summary>镇压开始时,玩家持有的 CRT 被冻结一半的概率:黑市声望 0 时 40%,50 以上为 0。</summary>
|
||||
public static double CrtFreezeChance(double blackMarketRep) =>
|
||||
Math.Max(0, Tuning.CrtFreezeBase - blackMarketRep * Tuning.CrtFreezePerRep);
|
||||
Math.Max(0, Tuning.CrtFreezeBase - blackMarketRep * Tuning.CrtFreezePerRep) * StoryMods.Current.CrtFreeze;
|
||||
|
||||
public bool CraSubsidyLow => CraSubsidy <= Tuning.CraSubsidy0 * Tuning.CraSubsidyWarn;
|
||||
/// <summary>镇压开始时是否冻结玩家的 CRT:按黑市声望,声望越低越容易被黑市"出卖"。</summary>
|
||||
public static bool CrtFrozenByCrackdown(double blackMarketRep, Rng rng) => rng.Chance(CrtFreezeChance(blackMarketRep));
|
||||
|
||||
/// <summary>储备覆盖率 R/S。</summary>
|
||||
public double Ratio => Supply > 0 ? Reserve / Supply : 1;
|
||||
|
||||
/// <summary>崩盘线之上的储备(CRC):吃空即必然崩盘。预测盘和线索用它估预兆。</summary>
|
||||
public double Cushion => Reserve - Tuning.CraCrashRatio * Supply;
|
||||
public static double Cushion0 => Tuning.CraS0 * (Tuning.CraC0 - Tuning.CraCrashRatio);
|
||||
|
||||
/// <summary>每晚的垫子消耗:利息按无抵押的新 CRA 付出,每份把崩盘线抬高 CraCrashRatio。</summary>
|
||||
public static double CushionDrain(double stakedTotal, double rate) => stakedTotal * rate * Tuning.CraCrashRatio;
|
||||
|
||||
/// <summary>储备覆盖率对应的价格:高于安全线为 1,线性降到崩盘线的 1 − CraDiscountMax。</summary>
|
||||
public static double PriceOfRatio(double r)
|
||||
{
|
||||
if (r >= Tuning.CraSafeRatio) return 1;
|
||||
double t = Math.Max(0, (r - Tuning.CraCrashRatio) / (Tuning.CraSafeRatio - Tuning.CraCrashRatio));
|
||||
return 1 - Tuning.CraDiscountMax * (1 - t);
|
||||
}
|
||||
|
||||
/// <summary>铸造 cra 个 CRA 要的 CRC 和 SPARK 数量(SPARK 部分按现价折算)。</summary>
|
||||
public void Collateral(double cra, out double crc, out double spark)
|
||||
{
|
||||
crc = cra * C;
|
||||
spark = Spark > 0 ? cra * (1 - C) / Spark : 0;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 铸造申请:从钱包扣 CRC 和 SPARK,排队 CraMintDaysMin..Max 天,到期铸出 CRA。余额不足返回 null。
|
||||
/// </summary>
|
||||
public CraOrder RequestMint(Wallet w, double cra, int day, Rng rng)
|
||||
{
|
||||
if (cra <= 0) return null;
|
||||
Collateral(cra, out double crc, out double spark);
|
||||
if (w.Avail(Assets.CRC) + 1e-9 < crc || w.Avail(Assets.SPARK) + 1e-9 < spark) return null;
|
||||
w.Add(Assets.CRC, -crc); w.Add(Assets.SPARK, -spark);
|
||||
var o = new CraOrder { Id = ++OrderSeq, Wallet = w.Address, Mint = true, Cra = cra, Crc = crc, Spark = spark, C = C, Due = day + rng.Range(Tuning.CraMintDaysMin, Tuning.CraMintDaysMax) };
|
||||
Orders.Add(o);
|
||||
return o;
|
||||
}
|
||||
|
||||
/// <summary>销毁申请:从钱包扣 CRA,排队 CraUnlockDays 天,到期换回 CRC 和 SPARK。余额不足返回 null。</summary>
|
||||
public CraOrder RequestBurn(Wallet w, double cra, int day)
|
||||
{
|
||||
if (cra <= 0 || w.Avail(Assets.CRA) + 1e-9 < cra) return null;
|
||||
w.Add(Assets.CRA, -cra);
|
||||
var o = new CraOrder { Id = ++OrderSeq, Wallet = w.Address, Mint = false, Cra = cra, C = C, Due = day + Tuning.CraUnlockDays };
|
||||
Orders.Add(o);
|
||||
return o;
|
||||
}
|
||||
|
||||
/// <summary>官方每晚黑掉一笔排队单的概率:系数 × (1 − CRA 价格),价格不低于 1 时为 0。</summary>
|
||||
public double RugChance => Math.Max(0, 1 - Cra) * Tuning.CraRugPerDepeg;
|
||||
|
||||
public bool CraSubsidyLow => Cushion <= Cushion0 * Tuning.CraSubsidyWarn;
|
||||
|
||||
/// <summary>CRA 的预兆:外生螺旋的新闻已出,或补贴池告急(利率下调)。螺旋开始后不再算预兆。</summary>
|
||||
public bool CraWarning(int day) => (CraWarnDay >= 0 && CraWarnDay <= day || CraSubsidyLow) && Cra >= 0.97;
|
||||
public bool CraWarning(int day) => (CraWarnDay >= 0 && CraWarnDay <= day || CraSubsidyLow) && CraCrashDay < 0 && Cra >= 0.97;
|
||||
|
||||
public double CraRate => CraSubsidyLow ? Tuning.CraRateLow : Tuning.CraRate;
|
||||
|
||||
/// <summary>
|
||||
/// 夜间结算。返回 CRC 持有量要乘的系数(减记兑现时为 0.95,否则为 1)。
|
||||
/// playerStaked:玩家的 CRA 质押额,用来算补贴支出(玩家的利息由调用方按 <see cref="CraRate"/> 发放)。
|
||||
/// playerStaked:玩家的 CRA 质押额,用来算利息带来的稀释(玩家的利息由调用方按 <see cref="CraRate"/> 发放)。
|
||||
/// </summary>
|
||||
public double Night(int day, Rng rng, double playerStaked)
|
||||
{
|
||||
@@ -79,21 +163,87 @@ namespace Decentralized.Domain
|
||||
if (RevHistory.Count > 7) RevHistory.RemoveAt(0);
|
||||
RevPower = Math.Max(0, Math.Min(100, RevPower + rng.Gauss() * 3));
|
||||
|
||||
if (CraSpiralDay < 0)
|
||||
if (CraCrashDay < 0)
|
||||
{
|
||||
CraSubsidy -= (Tuning.CraNpcStake + playerStaked) * CraRate;
|
||||
bool revFalling = RevHistory.Count == 7 && RevPower < RevHistory[0] - 5;
|
||||
double weekly = Tuning.CraSpiralWeekly * (revFalling ? 3 : 1);
|
||||
double daily = 1 - Math.Pow(1 - weekly, 1.0 / 7);
|
||||
if (CraWarnDay < 0 && (rng.Chance(daily) || CraSubsidy <= 0))
|
||||
double interest = (Tuning.CraNpcStake + playerStaked) * CraRate;
|
||||
Supply += interest;
|
||||
// 抵押率调整:价格低于 1 上调,回到 1 下调;兑付的 CRC 份额不超过储备均值(见 <see cref="Redeem"/>)
|
||||
if (Cra < 0.995) C = Math.Min(1, C + Tuning.CraCrStep);
|
||||
else if (Cra >= 0.999) C = Math.Max(Tuning.CraCrMin, C - Tuning.CraCrStep);
|
||||
if (CraEventDay < 0)
|
||||
{
|
||||
CraWarnDay = day;
|
||||
CraSpiralDay = day + rng.Range(Tuning.CraWarnLeadMin, Tuning.CraWarnLeadMax);
|
||||
bool revFalling = RevHistory.Count == 7 && RevPower < RevHistory[0] - 5;
|
||||
double weekly = Tuning.CraSpiralWeekly * (revFalling ? 3 : 1) * StoryMods.Current.CraSpiral(day);
|
||||
double daily = 1 - Math.Pow(1 - weekly, 1.0 / 7);
|
||||
if (rng.Chance(daily) || Cushion <= 0)
|
||||
{
|
||||
CraWarnDay = day;
|
||||
CraEventDay = day + rng.Range(Tuning.CraWarnLeadMin, Tuning.CraWarnLeadMax);
|
||||
}
|
||||
}
|
||||
else if (day >= CraEventDay)
|
||||
{
|
||||
// 挪用:储备被革命军拿走一部分,R/S 掉到崩盘线以下就是挤兑
|
||||
Reserve *= 1 - rng.Range(Tuning.CraEmbezzleMin, Tuning.CraEmbezzleMax);
|
||||
CraEventDay = -1; CraWarnDay = -1;
|
||||
if (Ratio < Tuning.CraCrashRatio) CraCrashDay = day;
|
||||
}
|
||||
}
|
||||
if (CraSpiralDay > 0 && day >= CraSpiralDay)
|
||||
Cra = Tuning.CraSpiralPath[Math.Min(day - CraSpiralDay, Tuning.CraSpiralPath.Length - 1)];
|
||||
if (CraCrashDay >= 0)
|
||||
{
|
||||
int k = Math.Min(day - CraCrashDay, Tuning.CraSpiralPath.Length - 1);
|
||||
Cra = Tuning.CraSpiralPath[k];
|
||||
if (SparkPre < 0) SparkPre = Spark;
|
||||
Spark = SparkPre * Tuning.SparkSpiralPath[Math.Min(day - CraCrashDay, Tuning.SparkSpiralPath.Length - 1)];
|
||||
}
|
||||
else
|
||||
{
|
||||
Cra = PriceOfRatio(Ratio);
|
||||
Spark *= Math.Exp(rng.Gauss() * Tuning.SparkVol) * StoryMods.Current.TakeSparkPush();
|
||||
Spark += (Tuning.SparkStart - Spark) * Tuning.SparkRevert;
|
||||
Spark = Math.Max(Tuning.SparkStart * Tuning.SparkMinMult, Math.Min(Tuning.SparkStart * Tuning.SparkMaxMult, Spark));
|
||||
}
|
||||
return crcFactor;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 销毁一份 CRA 的兑付:CRC 份额 = min(申请时的 c, 储备均值 R/S),其余按现价用新增发的 SPARK 补。
|
||||
/// 返回 (CRC 数量, SPARK 数量),并扣减储备和流通量。
|
||||
/// </summary>
|
||||
public void Redeem(double cra, double c, out double crc, out double spark)
|
||||
{
|
||||
double share = Math.Min(c, Ratio);
|
||||
crc = Math.Min(Reserve, cra * share);
|
||||
spark = Spark > 0 ? cra * (1 - crc / Math.Max(1e-9, cra)) / Spark : 0;
|
||||
Reserve -= crc; Supply = Math.Max(0, Supply - cra);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 夜间处理排队单:先对每一笔掷官方跑路(整笔丢失),再结算到期的。
|
||||
/// 铸造到期:CRC 进储备、SPARK 销毁、流通量增加;销毁到期:按 <see cref="Redeem"/> 兑付。
|
||||
/// </summary>
|
||||
public List<CraOrderEvent> NightOrders(int day, Rng rng)
|
||||
{
|
||||
var evs = new List<CraOrderEvent>();
|
||||
foreach (var o in Orders.ToList())
|
||||
{
|
||||
if (rng.Chance(RugChance)) { Orders.Remove(o); evs.Add(new CraOrderEvent { Order = o, Kind = CraOrderKind.Lost }); continue; }
|
||||
if (day < o.Due) continue;
|
||||
Orders.Remove(o);
|
||||
var ev = new CraOrderEvent { Order = o };
|
||||
if (o.Mint)
|
||||
{
|
||||
Supply += o.Cra; Reserve += o.Crc;
|
||||
ev.Kind = CraOrderKind.Minted; ev.Cra = o.Cra;
|
||||
}
|
||||
else
|
||||
{
|
||||
Redeem(o.Cra, o.C, out ev.Crc, out ev.Spark);
|
||||
ev.Kind = CraOrderKind.Burned;
|
||||
}
|
||||
evs.Add(ev);
|
||||
}
|
||||
return evs;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,90 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
|
||||
namespace Decentralized.Domain
|
||||
{
|
||||
/// <summary>一个钱包在革命军质押池里的仓位:计息的本金、排队等解锁的部分,以及存入时带来的污点与成本。</summary>
|
||||
public sealed class StakeLot
|
||||
{
|
||||
public string Wallet;
|
||||
public double Amount;
|
||||
public List<KeyValuePair<int, double>> Unlocking = new List<KeyValuePair<int, double>>();
|
||||
public double Taint, Basis;
|
||||
|
||||
public double Total => Amount + Unlocking.Sum(u => u.Value);
|
||||
}
|
||||
|
||||
/// <summary>一次到期或利息的结果,供夜间日志使用。</summary>
|
||||
public sealed class StakeEvent
|
||||
{
|
||||
public string Wallet;
|
||||
public double Interest, Released;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 革命军 CRA 质押池:质押的 CRA 每晚按日息计息(利息并入本金),取出要先申请,等 <see cref="Tuning.CraUnlockDays"/> 天,期间不计息、
|
||||
/// 也不能提前取。到期自动回到质押时的钱包。质押的币不会被冻结,但仓位里仍是 CRA:螺旋来临时到期取回的币只值当时的价格。
|
||||
/// 污点与成本随币存入、按比例随币取出。
|
||||
/// </summary>
|
||||
public sealed class Staking
|
||||
{
|
||||
public List<StakeLot> Lots = new List<StakeLot>();
|
||||
|
||||
public StakeLot Of(string wallet) => Lots.Find(l => ChainAddress.Same(l.Wallet, wallet));
|
||||
|
||||
/// <summary>全部计息中的质押量,补贴池按它算支出。</summary>
|
||||
public double Earning => Lots.Sum(l => l.Amount);
|
||||
|
||||
/// <summary>质押:从钱包取出 CRA,污点与成本按价值比例随币留在仓位里。余额不足返回 false。</summary>
|
||||
public bool Stake(Wallet w, double amount, Func<string, double> price)
|
||||
{
|
||||
if (amount <= 0 || w.Avail(Assets.CRA) + 1e-9 < amount) return false;
|
||||
double total = w.Value(price);
|
||||
double share = total > 0 ? Math.Min(1, amount * price(Assets.CRA) / total) : 0;
|
||||
double taint = w.Taint * share, basis = w.Basis * share;
|
||||
w.Add(Assets.CRA, -amount); w.Taint -= taint; w.Basis -= basis;
|
||||
var lot = Of(w.Address) ?? AddLot(w.Address);
|
||||
lot.Amount += amount; lot.Taint += taint; lot.Basis += basis;
|
||||
return true;
|
||||
}
|
||||
|
||||
private StakeLot AddLot(string wallet) { var l = new StakeLot { Wallet = wallet }; Lots.Add(l); return l; }
|
||||
|
||||
/// <summary>申请取出:这部分从计息本金里挪到排队区,day + 解锁天数 到期。额度不足返回 false。</summary>
|
||||
public bool RequestUnstake(string wallet, double amount, int day)
|
||||
{
|
||||
var lot = Of(wallet);
|
||||
if (lot == null || amount <= 0 || lot.Amount + 1e-9 < amount) return false;
|
||||
lot.Amount -= amount;
|
||||
lot.Unlocking.Add(new KeyValuePair<int, double>(day + Tuning.CraUnlockDays, amount));
|
||||
return true;
|
||||
}
|
||||
|
||||
/// <summary>每晚:计息(日息 rate,利息并入本金),到期的部分回到钱包。返回有变化的仓位。</summary>
|
||||
public List<StakeEvent> Night(int day, double rate, Func<string, Wallet> wallet)
|
||||
{
|
||||
var evs = new List<StakeEvent>();
|
||||
foreach (var lot in Lots.ToList())
|
||||
{
|
||||
var ev = new StakeEvent { Wallet = lot.Wallet };
|
||||
ev.Interest = lot.Amount * rate;
|
||||
lot.Amount += ev.Interest;
|
||||
foreach (var u in lot.Unlocking.Where(x => day >= x.Key).ToList())
|
||||
{
|
||||
double total = lot.Total;
|
||||
double share = total > 0 ? Math.Min(1, u.Value / total) : 0;
|
||||
double taint = lot.Taint * share, basis = lot.Basis * share;
|
||||
lot.Taint -= taint; lot.Basis -= basis;
|
||||
lot.Unlocking.Remove(u);
|
||||
var w = wallet(lot.Wallet);
|
||||
w.Add(Assets.CRA, u.Value); w.Taint += taint; w.Basis += basis;
|
||||
ev.Released += u.Value;
|
||||
}
|
||||
if (lot.Total < 1e-9) Lots.Remove(lot);
|
||||
if (ev.Interest > 0 || ev.Released > 0) evs.Add(ev);
|
||||
}
|
||||
return evs;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,143 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
|
||||
namespace Decentralized.Domain
|
||||
{
|
||||
/// <summary>
|
||||
/// 游戏剧情选择对本 mod 世界的影响:一组倍率和期限,随存档保存。各处的概率读 <see cref="Current"/>(接入层读档时指向存档里的这一份)。
|
||||
/// 每个选择只生效一次(Applied 记下键)。
|
||||
/// </summary>
|
||||
public sealed class StoryMods
|
||||
{
|
||||
/// <summary>当前生效的那一份。接入层读档时设成存档里的;测试里可以换。</summary>
|
||||
public static StoryMods Current = new StoryMods();
|
||||
|
||||
public List<string> Applied = new List<string>();
|
||||
/// <summary>CRC 脱锚、CRC 托管银行减记、CRT 脱锚、镇压时 CRT 被出卖的概率倍率(永久)。</summary>
|
||||
public double CrcDepeg = 1, CrcHaircut = 1, CrtDepeg = 1, CrtFreeze = 1;
|
||||
/// <summary>到这一天之前 CRA 螺旋概率减半。</summary>
|
||||
public int CraSafeUntil = -1;
|
||||
/// <summary>治安部整顿到这一天:出金审查命中率、混币器制裁概率、操纵与内幕查处概率上调。</summary>
|
||||
public int SecUntil = -1;
|
||||
/// <summary>伦警官被捕后的立威期到这一天:出金审查、操纵、内幕查处概率上调。</summary>
|
||||
public int LunUntil = -1;
|
||||
/// <summary>SPARK 每晚额外乘的倍数,还剩几晚。</summary>
|
||||
public double SparkPush = 1;
|
||||
public int SparkPushNights;
|
||||
/// <summary>混币器:手续费、匿名集(NPC 混币量)、跑路概率的倍率;被举报后永久关闭(在途的照常提回,不能再存)。</summary>
|
||||
public double MixerFee = 1, MixerVolume = 1, MixerRug = 1;
|
||||
public bool MixerClosed;
|
||||
/// <summary>本 mod 自己的剧情线:混币器运营者 Tumbler。</summary>
|
||||
public Tumbler Tumbler = new Tumbler();
|
||||
|
||||
public bool Has(string key) => Applied.Contains(key);
|
||||
|
||||
public double CraSpiral(int day) => day < CraSafeUntil ? Tuning.StoryCraSpiralMult : 1;
|
||||
public double Aml(int day) => (day < SecUntil ? Tuning.StorySecAmlMult : 1) * (day < LunUntil ? Tuning.StoryLunMult : 1);
|
||||
public double Sanction(int day) => day < SecUntil ? Tuning.StorySecSanctionMult : 1;
|
||||
/// <summary>操纵检出、内幕查处的概率倍率。</summary>
|
||||
public double Enforce(int day) => (day < SecUntil ? Tuning.StorySecEnforceMult : 1) * (day < LunUntil ? Tuning.StoryLunMult : 1);
|
||||
|
||||
/// <summary>每晚取 SPARK 的额外倍数(推完就是 1)。</summary>
|
||||
public double TakeSparkPush()
|
||||
{
|
||||
if (SparkPushNights <= 0) return 1;
|
||||
SparkPushNights--;
|
||||
return SparkPush;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 记下一个剧情选择并设置倍率。返回 false 表示已经生效过。CRA 补贴池的注资由接入层做(这里只管倍率)。
|
||||
/// key:serpico_rev / serpico_bm / serpico_sec / eleanor_leak / eleanor_return / lun_arrested。
|
||||
/// </summary>
|
||||
public bool Apply(string key, int day)
|
||||
{
|
||||
if (Has(key)) return false;
|
||||
Applied.Add(key);
|
||||
switch (key)
|
||||
{
|
||||
case "serpico_rev":
|
||||
CraSafeUntil = day + Tuning.StorySecDays;
|
||||
PushSpark(Tuning.StorySerpicoSpark);
|
||||
break;
|
||||
case "serpico_bm":
|
||||
CrtDepeg *= Tuning.StoryBmCrtMult; CrtFreeze *= Tuning.StoryBmCrtMult;
|
||||
break;
|
||||
case "serpico_sec":
|
||||
SecUntil = day + Tuning.StorySecDays;
|
||||
break;
|
||||
case "eleanor_leak":
|
||||
CrcHaircut *= Tuning.StoryLeakHaircutMult;
|
||||
PushSpark(Tuning.StoryLeakSpark);
|
||||
break;
|
||||
case "eleanor_return":
|
||||
CrcDepeg *= Tuning.StoryReturnCrcMult;
|
||||
break;
|
||||
case "lun_arrested":
|
||||
LunUntil = day + Tuning.StoryLunDays;
|
||||
break;
|
||||
case "tumbler_kept":
|
||||
MixerFee *= Tuning.TumblerKeptFee; MixerVolume *= Tuning.TumblerKeptVolume;
|
||||
break;
|
||||
case "tumbler_reported":
|
||||
MixerClosed = true;
|
||||
break;
|
||||
case "tumbler_sold":
|
||||
MixerFee *= Tuning.TumblerSoldFee; MixerRug *= Tuning.TumblerSoldRug;
|
||||
break;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
/// <summary>SPARK 在接下来几晚里一共涨到 total 倍(每晚乘相同的倍数)。</summary>
|
||||
private void PushSpark(double total)
|
||||
{
|
||||
int n = Tuning.StorySparkNights;
|
||||
// 已经在推:把剩下的叠上去
|
||||
double left = SparkPushNights > 0 ? Math.Pow(SparkPush, SparkPushNights) : 1;
|
||||
SparkPush = Math.Pow(left * total, 1.0 / n);
|
||||
SparkPushNights = n;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 混币器运营者 Tumbler 的剧情线:解锁混币器、第 <see cref="Tuning.TumblerMinDay"/> 天起开始,四次上门。
|
||||
/// 1 自我介绍 → 2 说治安部在追查混币器(当晚混币器被制裁)→ 3 求你藏密钥盘(三选一:藏 / 举报 / 卖给黑市)→ 4 结局。
|
||||
/// 只记进度,对话和物品在接入层。
|
||||
/// </summary>
|
||||
public sealed class Tumbler
|
||||
{
|
||||
public const int Hide = 1, Report = 2, Sell = 3;
|
||||
public int StartDay = -1, Stage, Choice, VisitedDay = -1;
|
||||
public bool Done;
|
||||
|
||||
/// <summary>第几次上门在哪一天(相对开始日)。</summary>
|
||||
public static readonly int[] Offsets = { 0, 3, 5, 9 };
|
||||
|
||||
public int NextVisitDay => StartDay < 0 || Stage >= Offsets.Length ? -1 : StartDay + Offsets[Stage];
|
||||
|
||||
/// <summary>每天开门时问:是否开始(明天第一次上门)。</summary>
|
||||
public bool TryStart(int day, bool mixerUnlocked)
|
||||
{
|
||||
if (StartDay >= 0 || Done || !mixerUnlocked || day < Tuning.TumblerMinDay) return false;
|
||||
StartDay = day + 1;
|
||||
return true;
|
||||
}
|
||||
|
||||
/// <summary>今天该上门的是第几次(1–4),没有就返回 0(第 4 次举报过的话由接入层改成新闻:他被抓了)。</summary>
|
||||
public int Due(int day)
|
||||
{
|
||||
if (Done || StartDay < 0 || Stage >= Offsets.Length || VisitedDay == day) return 0;
|
||||
if (day < NextVisitDay) return 0;
|
||||
return Stage + 1;
|
||||
}
|
||||
|
||||
/// <summary>这一次上门已经安排了。</summary>
|
||||
public void Visited(int day)
|
||||
{
|
||||
VisitedDay = day;
|
||||
Stage++;
|
||||
Done = Stage >= Offsets.Length;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -5,10 +5,21 @@ namespace Decentralized.Domain
|
||||
/// </summary>
|
||||
public static class Tuning
|
||||
{
|
||||
/// <summary>人脉网络升级价格:Web3 治理社区(入口)、混币器。</summary>
|
||||
public const int UnlockPrice = 400, MixerUnlockPrice = 300;
|
||||
|
||||
// 挖矿
|
||||
public const double PscStartPrice = 100;
|
||||
public const double BlockReward = 90;
|
||||
public const double BlockReward = 100;
|
||||
public const int HalvingDays = 90;
|
||||
/// <summary>减半对币价的传导:每次减半在区间内随机一个指数,价格锚上移 2^指数 倍(0.15–0.85 即约 +11% 到 +80%)。
|
||||
/// 参考比特币:每次减半后的涨幅差别很大,市场也已部分预期到,所以既不固定也不翻倍。</summary>
|
||||
public const double HalvingPassMin = 0.15, HalvingPassMax = 0.85;
|
||||
/// <summary>减半前一周的预期行情:锚逐日抬高,到减半当天为 +8%。</summary>
|
||||
public const int HalvingRampDays = 7;
|
||||
public const double HalvingRamp = 0.08;
|
||||
/// <summary>价格锚向目标的逐晚靠拢比例(约 7 天完成大半)。</summary>
|
||||
public const double SupplyAdjust = 0.15;
|
||||
public const double NpcHash0 = 360;
|
||||
public const double NpcKjPerH = 2.4;
|
||||
public const double ElecPrice = 1.5;
|
||||
@@ -22,8 +33,17 @@ namespace Decentralized.Domain
|
||||
public const double RefurbishHealth = 30;
|
||||
|
||||
// 市场
|
||||
public const double PoolDepth0 = 50000;
|
||||
public const double DexFee = 0.003, ExchangeFee = 0.002;
|
||||
/// <summary>交易对信用点一侧的基础深度(DEX 侧池按比例取)。</summary>
|
||||
public const double PoolDepth0 = 600000;
|
||||
/// <summary>Poinbase 订单簿的冲击曲线:价格 = 参考价 × exp(κ · |x|^α),x = 当天净买入的名义价值 / 深度。第 38 天买 2 PSC 平均滑点约 0.1%,卖 200 PSC 约 4%。</summary>
|
||||
public const double BookK = 1.54, BookAlpha = 0.8;
|
||||
/// <summary>DEX 手续费;Poinbase 现货与出金的手续费(对照头部交易所 taker 约 0.1%)。</summary>
|
||||
public const double DexFee = 0.003, ExchangeFee = 0.001;
|
||||
/// <summary>DEX 稳定币对(CRT/CRC、CRA/CRC)的 StableSwap 池:手续费(参考 Curve 3pool 0.04%)、放大系数;
|
||||
/// 参考价偏离挂钩超过 1% 是脱锚(流动性变差,A 降到 20,参考 USDC 2023 年 3 月最低约 0.87、两三天回到 1),超过 15% 是崩盘(流动性被撤走,A 降到 1、深度只剩四分之一)。</summary>
|
||||
public const double StableFee = 0.0004, StableAmp = 200, StableAmpDepeg = 20, StableAmpBroken = 1, StableDepegBand = 0.01, StableBrokenBand = 0.15, StableBrokenDepth = 0.25;
|
||||
/// <summary>NPC 大户每笔成交额(信用点)的范围。</summary>
|
||||
public const double WhaleMin = 24000, WhaleMax = 96000;
|
||||
public const double Revert = 0.15;
|
||||
public const double PscVol = 0.04;
|
||||
public const double SentimentKappa = 0.02, SentimentVol = 0.02;
|
||||
@@ -32,7 +52,7 @@ namespace Decentralized.Domain
|
||||
// 稳定币
|
||||
public const double CrcDepegChance = 0.30, CrcDepegMin = 0.88, CrcDepegMax = 0.93;
|
||||
public const int CrcDepegDaysMin = 2, CrcDepegDaysMax = 3;
|
||||
public const double CrcHaircutChance = 0.15, CrcHaircut = 0.95;
|
||||
public const double CrcHaircutChance = 0.15, CrcHaircut = 0.85;
|
||||
public const double CrtDepegChance = 0.40, CrtDepegMin = 0.92, CrtDepegMax = 0.96;
|
||||
public const int CrtDepegDaysMin = 1, CrtDepegDaysMax = 2;
|
||||
public const double CrtFreezeBase = 0.40, CrtFreezePerRep = 0.008, CrtFreezeShare = 0.5;
|
||||
@@ -40,20 +60,272 @@ namespace Decentralized.Domain
|
||||
public const double CrtSwapFee = 0.02;
|
||||
public const double CraRate = 0.005, CraRateLow = 0.002;
|
||||
public const int CraUnlockDays = 4;
|
||||
public const double CraSubsidy0 = 30000, CraSubsidyWarn = 0.2, CraNpcStake = 20000;
|
||||
public const double CraSpiralWeekly = 0.02;
|
||||
public const double CraSubsidyWarn = 0.2, CraNpcStake = 20000;
|
||||
/// <summary>CRA 部分抵押:初始流通量与抵押率、抵押率下限与每晚调整步长;R/S 安全线、崩盘线、安全线到崩盘线之间的最大折价;
|
||||
/// 挪用储备的比例范围;劫掠上层补回的储备(占流通量);一级市场铸造等待天数;官方跑路系数(× (1 − CRA 价格))。数值由 research/crasim 定。</summary>
|
||||
public const double CraS0 = 60000, CraC0 = 0.8, CraCrMin = 0.5, CraCrStep = 0.02;
|
||||
public const double CraSafeRatio = 0.6, CraCrashRatio = 0.35, CraDiscountMax = 0.15;
|
||||
public const double CraEmbezzleMin = 0.4, CraEmbezzleMax = 0.8, CraLoot = 0.09;
|
||||
public const int CraMintDaysMin = 1, CraMintDaysMax = 2;
|
||||
public const double CraRugPerDepeg = 1;
|
||||
/// <summary>Poinbase 出金到钱包的确认动画:基础秒数,加每个确认的秒数(确认数同 PLEDGER 的 TxConfirm*)。</summary>
|
||||
public const double FundsBaseSecs = 1.2, FundsConfSecs = 0.6;
|
||||
/// <summary>浏览器账本最多保留的转账条数,一次最多显示的条数。</summary>
|
||||
public const int LedgerMax = 500, LedgerShow = 12;
|
||||
public const double CraSpiralWeekly = 0.03;
|
||||
public const int CraWarnLeadMin = 4, CraWarnLeadMax = 7;
|
||||
public static readonly double[] CraSpiralPath = { 0.85, 0.30, 0.02 };
|
||||
/// <summary>平衡代币 SPARK:起始价与长期锚(信用点)、日波动率、每晚向锚回归的比例、价格上下限(锚的倍数);铸销手续费;
|
||||
/// 革命军袭击上层 / 下层动荡开始时的冲击;CRA 死亡螺旋三天里相对螺旋前价格的倍数。</summary>
|
||||
public const double SparkStart = 10, SparkVol = 0.08, SparkRevert = 0.03, SparkMinMult = 0.3, SparkMaxMult = 3, SparkFee = 0.003;
|
||||
public const double SparkRaidShock = 1.15, SparkUnrestShock = 0.90;
|
||||
public static readonly double[] SparkSpiralPath = { 0.8, 0.3, 0.05 };
|
||||
|
||||
// 合规出金与 AML(阈值以当前房租为单位)
|
||||
public const double AmlBigRents = 5, AmlCumRents = 15;
|
||||
/// <summary>出金审查命中概率:污点占比达标后每占一分加 AmlTaintMult 倍;超出单笔 / 累计额度的部分按 AmlExcessWeight 加。</summary>
|
||||
public const double AmlTaintMult = 1.5, AmlExcessWeight = 0.2;
|
||||
public const int AmlWindowDays = 7;
|
||||
public const double AmlTaintRatio = 0.10, AmlHeavyRatio = 0.30, AmlMixerBonus = 0.30, AmlMaxChance = 0.9;
|
||||
public const double TaxRate = 0.08;
|
||||
/// <summary>混币器:每轮手续费、基准清洗率、NPC 背景量(信用点)、最大轮数、最小存入、制裁概率与天数、每晚跑路概率。</summary>
|
||||
public const double MixerFee = 0.03, MixerCleanRate = 0.35, MixerNpcVolume = 20000, MixerMin = 100, MixerSanctionChance = 0.5, MixerRugChance = 0.004;
|
||||
public const int MixerMaxRounds = 5, MixerSanctionDays = 5;
|
||||
/// <summary>各派系顾客用币付款的概率。</summary>
|
||||
public const double CoinPayCrc = 0.30, CoinPayCrt = 0.50, CoinPayCra = 0.50, CoinPayPsc = 0.25;
|
||||
/// <summary>用币付款的溢价:顾客多付的比例,补偿持币的污点与兑出的手续费。</summary>
|
||||
public const double CoinPayPremium = 0.12;
|
||||
/// <summary>顾客验货:说法里每一项隐瞒被看穿的概率;型号档次不符(供电口、风扇数一眼可见)必被看穿;一次看穿最多扣的信誉。</summary>
|
||||
public const double CustomerSpotChance = 0.50, CustomerSpotTierMismatch = 1.0;
|
||||
public const int RepLossMax = 25;
|
||||
/// <summary>杰克逊博士上货:进阶 / 旗舰货的起始天(有特殊进货渠道时旗舰第 20 天起),矿架补货、进阶货(及第二件)、旗舰货的概率。</summary>
|
||||
public const int DealerAdvancedFromDay = 10, DealerFlagshipFromDay = 30, DealerSpecialFlagshipFromDay = 20;
|
||||
public const double DealerRigRestock = 0.30, DealerAdvanced = 0.60, DealerAdvancedSecond = 0.30, DealerFlagship = 0.25;
|
||||
/// <summary>二手贩子:每天来访概率与最早来访日;骗子占比 = 基础 + 每天增量,封顶;中间商占比;中间商加价;中间商 / 骗子夹带假卡的比例;
|
||||
/// 中间商把每项问题说成没问题的概率(骗子全说)。</summary>
|
||||
public const double UsedVisitChance = 0.05, UsedScamBase = 0.10, UsedScamPerDay = 0.004, UsedScamMax = 0.30, UsedMiddlemanShare = 0.30;
|
||||
public const double UsedMiddlemanMarkup = 0.08, UsedFakeMiddleman = 0.10, UsedFakeScammer = 0.45, UsedMiddlemanHide = 0.70;
|
||||
public const int UsedFirstDay = 3;
|
||||
/// <summary>显卡价值 = 型号定价 ×(下限 + (1 − 下限) × 健康度)。</summary>
|
||||
public const double CardValueFloor = 0.25;
|
||||
/// <summary>假卡的四项真伪依据(风扇数、供电口、背面丝印、序列号)各自露出破绽的概率(至少露出一项);约对应平均 1.5 项。</summary>
|
||||
public const double FakeSignChance = 0.27;
|
||||
/// <summary>黑市、鉴定等处二手卡的健康度范围(均匀取)。</summary>
|
||||
public const double CardHealthMin = 25, CardHealthMax = 85;
|
||||
/// <summary>二手贩子带来的卡的健康度范围,按老实人、中间商、骗子:越不老实卡越旧,平均每张卡约 0.5 / 1.5 / 2.5 项成色问题(叶片、金手指、挡板、封条)。</summary>
|
||||
public static readonly double[] UsedHealthMin = { 72, 55, 42 }, UsedHealthMax = { 97, 85, 72 };
|
||||
/// <summary>外观折价(占价值的比例):叶片积灰 / 缺角,金手指发暗 / 氧化,挡板划痕,封条缺失。</summary>
|
||||
public const double CardFanDust = 0.04, CardFanChipped = 0.12, CardFingersDark = 0.04, CardFingersOxidized = 0.12, CardBracketScratch = 0.02, CardSealMissing = 0.06;
|
||||
/// <summary>非主交易对每晚被拉回参考价的比例,及其深度占主交易对的比例。</summary>
|
||||
public const double SideArbRate = 0.75, SideDepthShare = 0.3, SparkDepthShare = 0.15;
|
||||
/// <summary>Poinbase 的 SPARK/CRC 订单簿深度占主池深度的比例。</summary>
|
||||
public const double PoinSparkDepthShare = 0.5;
|
||||
/// <summary>Web3 黑市:开放所需黑市声望,中 / 高档货所需声望,现货每周刷新的天数与基础件数(每高 BmStockPerRep 声望多一件),现货溢价。</summary>
|
||||
public const int BmOpenRep = 10, BmMidRep = 40, BmHighRep = 80, BmRefreshDays = 7, BmStockBase = 4;
|
||||
public const double BmStockPerRep = 40, BmPremium = 0.30;
|
||||
/// <summary>Ponero 兑换处:开放所需黑市声望、每次兑入 / 兑出的手续费、每天可兑换的额度(信用点)、对 PSC 的价格比。</summary>
|
||||
public const int PoneroOpenRep = 30;
|
||||
public const double PoneroFee = 0.06, PoneroDailyCap = 1000, PoneroPscRatio = 0.5;
|
||||
/// <summary>黑市订单:订单价相对游戏基础价的折扣、托管费、提前放款再折扣、提前放款所需卖家成交数、上门的天数、
|
||||
/// 上门被截获的概率(镇压期间再加)、骗子卖家占比、每晚平台跑路基础概率与每万信用点托管资金加的概率(封顶)、跑路后关闭的天数。</summary>
|
||||
public const double BmEscrowFee = 0.05, BmAdvanceDiscount = 0.10, BmInterceptDoor = 0.08, BmInterceptCrackdown = 0.15;
|
||||
public const double BmScamSellerShare = 0.15, BmRugBase = 0.002, BmRugPerTenK = 0.004, BmRugMax = 0.05;
|
||||
public const int BmAdvanceMinTrades = 30, BmDoorDays = 3, BmRugClosedDays = 10;
|
||||
/// <summary>蜜罐:每晚平台被执法接管的基础概率、每点治安声望加的概率、封顶、持续天数;之后订单被追查的延迟天数;
|
||||
/// 订单被截获时变成受控交付的概率;每晚某个近期卖家落网的概率。</summary>
|
||||
public const double BmHoneypotBase = 0.01, BmHoneypotPerSecRep = 0.0004, BmHoneypotMax = 0.06, BmControlled = 0.35, BmSellerBust = 0.008;
|
||||
public const int BmHoneypotDays = 6, BmTrapDelay = 4;
|
||||
/// <summary>商家货架的随机细节:现货每种的库存上限、每件价格的随机抖动(±)、全新矿卡的库存比常规少多少;尖端店铺里卖显卡的概率与显卡档次下限;
|
||||
/// 个人卖家里卖显卡的概率与其中全新的比例;骗子 / 诚实卖家是新号(成交少、好评随意)的概率;新号与老号的成交数、好评范围;论坛点名骗子的概率;
|
||||
/// 托管资金推高跑路概率超过基础的几倍时论坛出现"提币变慢"。</summary>
|
||||
public const int BmSpotQtyMax = 3, BmNewGpuQtyMinCut = 1, BmNewGpuQtyMaxCut = 2, BmEliteGpuTier = 3;
|
||||
public const double BmPriceJitter = 0.03, BmEliteGpuChance = 0.4, BmPersonalGpuChance = 0.15, BmPersonalGpuNew = 0.3, BmScamFresh = 0.6, BmHonestFresh = 0.25, BmForumScamHint = 0.5, BmForumRugFactor = 3;
|
||||
public const int BmFreshTradesMax = 12, BmOldTradesMin = 25, BmOldTradesMax = 220, BmScamOldRatingMin = 94, BmScamOldRatingMax = 99, BmFreshRatingMin = 70, BmFreshRatingMax = 100, BmOldRatingMin = 90, BmOldRatingMax = 99;
|
||||
/// <summary>追查记罪证:记入的比例(货款 × 比例)、同一次蜜罐(或一次落网)累计最多记多少。</summary>
|
||||
public const double BmTrapShare = 0.4, BmTrapWindowCap = 400;
|
||||
/// <summary>货架上除违禁品外的两类货:高科技物品(需中档声望)和显卡的出现概率、加价(在现货溢价 / 订单价之外再加),显卡里夹假卡的比例、是全新卡(成色 100、封条完好、不会是假卡)的概率。</summary>
|
||||
public const double BmTechChance = 0.30, BmGpuChance = 0.30, BmTechMarkup = 0.5, BmGpuMarkup = 0.2, BmGpuFake = 0.20, BmGpuNew = 0.15;
|
||||
/// <summary>玩家上架出售:标价倍率范围(相对参考价)、上架费、成交抽成、成交后货款托管天数、假卡被买家看穿的概率;
|
||||
/// 倍率 ≤0.9 / 1.0 / 1.8 时的期望成交天数(之间插值);货款带污点的概率与比例随倍率从下限涨到上限;卖家好评的初始值、看穿一次扣的点数、同时上架的件数上限。</summary>
|
||||
public const double BmListFee = 0.05, BmCommission = 0.08, BmSellMin = 0.6, BmSellMax = 1.8, BmFakeDetect = 0.5;
|
||||
/// <summary>出售成交天数的倍率界线:不高于 BmSellFastMult 倍用 BmSellDaysFast 天,BmSellDay1Mult 倍用 BmSellDays1 天,之间线性,再往上指数到 BmSellMax。</summary>
|
||||
public const double BmSellFastMult = 0.9, BmSellDay1Mult = 1.0;
|
||||
/// <summary>出售页可选的标价倍率档位。</summary>
|
||||
public static readonly double[] BmSellMults = { 0.6, 0.8, 0.9, 1.0, 1.2, 1.5, 1.8 };
|
||||
public const double BmSellDaysFast = 1, BmSellDays1 = 2, BmSellDaysMax = 14;
|
||||
public const double BmSaleTaintChanceMin = 0.2, BmSaleTaintChanceMax = 0.9, BmSaleTaintRatioMin = 0.2, BmSaleTaintRatioMax = 0.8;
|
||||
public const int BmSaleHold = 3, BmRatingStart = 90, BmRatingFakeLoss = 10;
|
||||
/// <summary>同时上架的货:最多几种(按商品标识),每种最多几件。</summary>
|
||||
public const int BmMaxKinds = 6, BmMaxStack = 5;
|
||||
/// <summary>收款币的买家权重:每接受一种币,夜间多一轮成交判定,轮次概率 = 成交概率 × 权重(CRT 为 1 即原有节奏)。</summary>
|
||||
public const double BmWeightPsc = 0.8, BmWeightCrt = 1, BmWeightCra = 0.6, BmWeightPonero = 0.4;
|
||||
/// <summary>PLEDGER 区块高度每晚自然增长的范围(区块数,含两端)。</summary>
|
||||
public const int BlocksPerDayMin = 120, BlocksPerDayMax = 170;
|
||||
/// <summary>商家货架:每周的商家数(其中 2 家从矿卡 / 矿架 / 模组 4 类里抽,其余从其他类型里抽)、每家的货种数、每种货的库存范围;大宗商家出现概率、库存范围、送货天数;
|
||||
/// 各类商家的价格系数范围(订单价 = 基础价 × 系数);批量折扣档(件数、折扣)。</summary>
|
||||
public const int BmMerchantCount = 7, BmCoreMerchants = 2, BmMerchantListings = 3, BmQtyMin = 2, BmQtyMax = 6, BmBulkQtyMin = 10, BmBulkQtyMax = 25, BmBulkDays = 6;
|
||||
public const double BmBulkChance = 0.25, BmFactorMin = 0.70, BmFactorMax = 0.95, BmFactorNewMin = 0.85, BmFactorNewMax = 1.00, BmFactorUsedMin = 0.65, BmFactorUsedMax = 0.90, BmFactorBulkMin = 0.55, BmFactorBulkMax = 0.75;
|
||||
/// <summary>商家货架上单件基础价的上限(过贵的货不上,免得一件把周转量撑歪)。</summary>
|
||||
public const long BmMaxUnitValue = 4000;
|
||||
/// <summary>尖端店铺:每周出现概率、货种数、库存范围、单件基础价下限、价格系数范围、送货天数。</summary>
|
||||
public const double BmEliteChance = 0.15, BmFactorEliteMin = 0.85, BmFactorEliteMax = 1.00;
|
||||
public const int BmEliteListings = 2, BmEliteQtyMax = 2, BmEliteDays = 5;
|
||||
public const long BmEliteMinValue = 2000;
|
||||
/// <summary>个人卖家:每周家数、货种数、库存上限、每件的价格系数范围(各件独立随机)、是骗子的概率、混进尖端货的概率。</summary>
|
||||
public const int BmPersonalCount = 2, BmPersonalListings = 3, BmPersonalQtyMax = 2;
|
||||
public const double BmPersonalFactorMin = 0.50, BmPersonalFactorMax = 1.20, BmPersonalScam = 0.25, BmPersonalEliteShare = 0.10;
|
||||
public const int BmBulk1Count = 5, BmBulk2Count = 10;
|
||||
public const double BmBulk1Discount = 0.05, BmBulk2Discount = 0.10;
|
||||
/// <summary>出售量越大货款越容易带污点:近 7 天成交额达到参考量时,污点概率与比例各加最多 BmVolumeTaintMax。</summary>
|
||||
public const double BmVolumeRef = 14000, BmVolumeTaintMax = 0.30;
|
||||
/// <summary>黑市人脉升级的价格。</summary>
|
||||
public const int BmUnlockPrice = 600;
|
||||
/// <summary>单个金融违规事件记入的罪证上限。</summary>
|
||||
public const double CrimeEventCap = 400;
|
||||
|
||||
/// <summary>硬件钱包:最多几个(含主钱包);杰克逊博士的售价与每次进货上架的概率;Web3 商城的价格范围、每周平台现货上架的概率与件数上限;商城货里被投毒的比例。</summary>
|
||||
public const int WalletMax = 5, WalletJacksonPrice = 240, WalletMallMin = 150, WalletMallMax = 180, WalletMallQtyMax = 2;
|
||||
public const double WalletJacksonChance = 0.5, WalletMallChance = 0.5, WalletPoisonShare = 0.2;
|
||||
/// <summary>被投毒的钱包:币的总价值达到 DrainMin 起,每晚有概率被转空;价值越高越快:期望天数从门槛处的 SlowDays(7 天)按价值线性降到 DrainFull 处的 1 天,每晚概率 = 1 / 期望天数。</summary>
|
||||
public const double WalletDrainMin = 3000, WalletDrainFull = 20000, WalletDrainSlowDays = 7;
|
||||
|
||||
/// <summary>转账手续费(信用点等值,按转出的币扣):慢 / 普通 / 快;拥堵时乘以倍数。</summary>
|
||||
public const double TxFeeSlow = 0.5, TxFeeNormal = 1.5, TxFeeFast = 4, TxCongestedFeeMult = 4;
|
||||
/// <summary>Gas 档位的确认速度倍数(时间乘它):Gas 越高确认越快、进度条走得越快;Poinbase 出金固定普通档。</summary>
|
||||
public const double TxSpeedSlow = 1.5, TxSpeedNormal = 1, TxSpeedFast = 0.5;
|
||||
/// <summary>PLEDGER 按住 ✓ 签名的基础秒数(普通档),乘档位速度倍数:快档更短、慢档更长。</summary>
|
||||
public const double TxHoldSecs = 1.2;
|
||||
/// <summary>Gas 价格指数:以 GasPeriod 天为周期正弦涨跌,振幅 GasAmp(0.5×–1.5×),每天再乘 1 ± GasNoise 的随机波动。</summary>
|
||||
public const int TxGasPeriod = 7;
|
||||
public const double TxGasAmp = 0.5, TxGasNoise = 0.15;
|
||||
/// <summary>网络拥堵:每晚开始拥堵的概率、持续天数上限;拥堵时普通档、慢档的确认间隔倍数,慢档被挤出内存池的概率。</summary>
|
||||
public const double TxCongestionChance = 0.12, TxCongestedNormalSlow = 2, TxCongestedSlowSlow = 3.5, TxSlowDrop = 0.3;
|
||||
public const int TxCongestionDaysMax = 2;
|
||||
/// <summary>确认数:默认 3;金额(信用点)≥ MidValue 时 6,≥ BigValue 时 12。</summary>
|
||||
public const int TxConfirmBase = 3, TxConfirmMid = 6, TxConfirmBig = 12;
|
||||
public const double TxConfirmMidValue = 2000, TxConfirmBigValue = 10000;
|
||||
/// <summary>地址投毒:每笔转出后被盯上的概率,0 币转入在 1–2 天后出现。剪贴板木马(被投毒的钱包):粘贴时换成相似地址的概率。钓鱼公告:每晚出现的概率。</summary>
|
||||
public const double TxPoisonChance = 0.35, TxHijackChance = 0.3, TxPhishChance = 0.05;
|
||||
public const int TxPoisonDelayMax = 2;
|
||||
|
||||
/// <summary>永续合约:开平仓手续费、强平费、维持保证金比例;保险基金初值(约 20 天的全网产出)、手续费进基金的比例;
|
||||
/// 基金见底时盈利仓位自动减仓的盈利折扣;资金费系数与上下限(每晚);欠款日息、没收宽限天数、核销后拉黑天数;两个品种的最高杠杆与单仓名义价值上限。</summary>
|
||||
public const double PerpFee = 0.001, PerpLiqFee = 0.02, PerpMaint = 0.10;
|
||||
public const double PerpFund0 = 200000, PerpFeeToFund = 0.3, PerpAdlHaircut = 0.5;
|
||||
/// <summary>NPC 永续仓位(每晚按标记价的涨跌结算,进出保险基金):亏损一侧的持仓占现货池深的倍数(SPARK 再乘 SparkDepthShare);
|
||||
/// 涨跌幅达到 PerpNpcLiqScale 时亏损一侧全部爆仓,之前按比例爆仓;爆仓里穿仓的比例 = 基础 + 斜率 × (涨跌幅 − 免穿仓幅度),封顶;
|
||||
/// 正常爆仓交给基金的剩余保证金(占名义价值);穿仓的缺口(占名义价值)= 涨跌幅 × 系数。</summary>
|
||||
public const double PerpNpcOi = 1.0, PerpNpcLiqScale = 0.25, PerpNpcBankBase = 0.05, PerpNpcBankSlope = 1.5, PerpNpcBankFree = 0.12, PerpNpcBankMax = 0.95;
|
||||
public const double PerpNpcLeft = 0.005, PerpNpcGap = 0.3;
|
||||
/// <summary>爆仓新闻:标记价单日涨跌达到多少上报纸;NPC 平均每个仓位的名义价值(折算人数)。</summary>
|
||||
public const double PerpNewsMove = 0.15, PerpNpcAvgPos = 1500;
|
||||
public const double PerpFundCoef = 0.10, PerpFundCap = 0.003;
|
||||
/// <summary>永续的成交深度占现货主池的比例:开平仓的平均滑点 = 名义价值 / (深度倍数 × 池深),和现货一样大单更贵。</summary>
|
||||
public const double PerpDepthMult = 5.0;
|
||||
/// <summary>永续成交深度的基数(与现货分开;原来 50,000,减半滑点后 100,000,校准见 research/perpsim)。</summary>
|
||||
public const double PerpDepth0 = 100000;
|
||||
/// <summary>开仓时按现价算权益至少要高出强平线多少(占名义价值的比例),否则拒绝(滑点太大,开了就被强平)。</summary>
|
||||
public const double PerpOpenBuffer = 0.02;
|
||||
public const double PerpDebtInterest = 0.02;
|
||||
public const int PerpDebtDays = 7, PerpBanDays = 30;
|
||||
public const int PerpPscLev = 5, PerpSparkLev = 3;
|
||||
public const double PerpPscCap = 20000, PerpSparkCap = 5000;
|
||||
|
||||
/// <summary>RatDigg 矿机(ASIC):黑市矿机商每周出现的概率;M1 / M2 / M3 需要的黑市声望与出现权重;新机占比与二手的健康度范围。</summary>
|
||||
public const double AsicChance = 0.25, AsicNewShare = 0.7;
|
||||
public const int AsicRepM1 = 40, AsicRepM2 = 60, AsicRepM3 = 80;
|
||||
public const double AsicWeightM1 = 1.0, AsicWeightM2 = 0.6, AsicWeightM3 = 0.4;
|
||||
public const int AsicUsedHealthMin = 40, AsicUsedHealthMax = 85;
|
||||
/// <summary>修好之后健康扣的点数;损坏的机器剩余价值占机价的比例。</summary>
|
||||
public const int AsicRepairHealthCut = 20;
|
||||
public const double AsicDeadValue = 0.15;
|
||||
/// <summary>"矿机时代":第几天到第几天之间随机发生一次(永久),提前几天上报纸;NPC 矿工的耗电乘数(耗电效率翻倍 = 0.5)。</summary>
|
||||
public const int EraMin = 50, EraMax = 90, EraWarnMin = 4, EraWarnMax = 7;
|
||||
public const double EraKjMult = 0.5;
|
||||
|
||||
/// <summary>预测市场:游戏第几天起开放;手续费;单盘额度 = 基础 + 每天增量 × 天数;所有钱包在单盘合计的份额上限(额度的倍数);
|
||||
/// 同时开放的盘口数量范围、每天最多新开几个;内幕持仓达到上限份额的多少比例后结算被查的概率,查实后收益记罪证的比例与上限;
|
||||
/// 派系行动的日均开始概率(先验);先验概率的夹紧范围;结算记录保留条数。</summary>
|
||||
public const int PredictUnlockDay = 8;
|
||||
public const double PredictFee = 0.01, PredictLoss0 = 800, PredictLossPerDay = 25, PredictCap = 2;
|
||||
/// <summary>预测盘的流动性:LMSR 的 b = 倍数 × 单盘额度 / ln 2,与先验无关(低先验盘不再更浅)。单盘额度只决定份额上限和消息价。</summary>
|
||||
public const double PredictDepth = 1.8;
|
||||
public const int PredictOpenMin = 3, PredictOpenMax = 6, PredictNewPerDay = 2;
|
||||
public const double PredictInsiderShare = 0.4, PredictInsiderCatch = 0.7, PredictFraudShare = 0.5, PredictFraudCap = 400;
|
||||
public const double PredictFactionDaily = 0.06, PredictPMin = 0.03, PredictPMax = 0.97;
|
||||
public const int PredictHistory = 8;
|
||||
/// <summary>gas 盘的公开价里"不知道相位"的权重:越大,数清七天周期的玩家越赚。金融审查(agy_fin/subsim)发现 0.5 时 gas 盘胜率 96%、每周净赚约 1,400,调到 0.15。</summary>
|
||||
public const double PredictGasBlind = 0.15;
|
||||
/// <summary>盘口对消息的反应:每晚向"公开信息下的合理概率"靠拢的比例,以及盘口 logit 上的随机噪声(NPC 流量)。</summary>
|
||||
public const double PredictDrift = 0.5, PredictNoise = 0.35;
|
||||
/// <summary>夜里价格变化超过多少(概率)写进晨间日志。</summary>
|
||||
public const double PredictMoveLog = 0.15;
|
||||
/// <summary>情报贩子:局势简报价格(CRT)、三档内幕消息的价格(占盘口最大亏损的比例)与准确率、假情报概率(claim 与真相相反)、需要的黑市声望。</summary>
|
||||
public const double IntelBriefPrice = 120, IntelFake = 0.10;
|
||||
public static readonly double[] IntelTipPrice = { 0.02, 0.05, 0.12 }, IntelTipAcc = { 0.60, 0.80, 0.95 };
|
||||
public const int IntelRep = 20;
|
||||
/// <summary>操纵检出:玩家自己的大单把价格推离"没有你时的水平"的对数幅度(取绝对值)低于 ManipFree 不查;
|
||||
/// 超过后被查概率 = ManipBase + ManipSlope × (幅度 − ManipFree),封顶 ManipMax;被查后永续账户冻结几天。</summary>
|
||||
public const double ManipFree = 0.16, ManipBase = 0.25, ManipSlope = 3, ManipMax = 0.95;
|
||||
public const int ManipFreezeDays = 3;
|
||||
|
||||
/// <summary>高息理财(庞氏):第几天起开放、开张的宣传费(CRC)、可选日息、每晚新存入的基数(随天数)和对日息的敏感指数、
|
||||
/// 池子上限(随天数)、每晚被取走的比例、每晚被举报概率(基础 + 日息系数 + 池子占上限的比例系数)、卷走或崩盘时记的罪证。</summary>
|
||||
public const int PonziMinDay = 15;
|
||||
public const double PonziAdCost = 800;
|
||||
public static readonly double[] PonziRates = { 0.02, 0.04, 0.06, 0.08, 0.10 };
|
||||
public const double PonziBase0 = 300, PonziBasePerDay = 15, PonziRateExp = 1.5;
|
||||
public const double PonziCap0 = 6000, PonziCapPerDay = 200, PonziWithdraw = 0.03;
|
||||
public const double PonziReport0 = 0.02, PonziReportRate = 0.5, PonziReportSize = 0.04;
|
||||
public const double PonziCrime = 400;
|
||||
|
||||
/// <summary>插针:每天开门时出现的概率、幅度范围(对数价格的绝对值)、当晚回去的比例范围、不回去(真跌真涨)的概率。</summary>
|
||||
public const double WickChance = 0.07, WickMin = 0.15, WickMax = 0.30, WickRevertMin = 0.6, WickRevertMax = 1.0, WickReal = 0.3;
|
||||
/// <summary>空投:每晚出现新空投的概率、有效天数、骗局占比、正规空投奖励范围(信用点等值)、钓鱼授权后被转走的延迟(晚)。</summary>
|
||||
public const double AirdropChance = 0.35, AirdropScam = 0.4, AirdropRewardMin = 20, AirdropRewardMax = 120;
|
||||
public const int AirdropDays = 2, AirdropDrainMin = 1, AirdropDrainMax = 2;
|
||||
/// <summary>第三方收益池:同时最多几个、每晚新开的概率;日息档位;按日息的骗局概率,时间锁、审计各减多少;骗局池每晚跑路概率;
|
||||
/// 单池存款上限(随天数);正规池的储备(日息 × 存款上限 × 天数);时间锁取款等待天数。</summary>
|
||||
public const int YieldPoolMax = 3, YieldLockDays = 2;
|
||||
public const double YieldPoolChance = 0.25, YieldRugNightly = 0.18, YieldCap0 = 4000, YieldCapPerDay = 120, YieldReserveDays = 25;
|
||||
public static readonly double[] YieldRates = { 0.01, 0.02, 0.03 }, YieldScamByRate = { 0.15, 0.40, 0.75 };
|
||||
public const double YieldScamTimelock = 0.25, YieldScamAudit = 0.20;
|
||||
/// <summary>收黑币:相关事件期间每天有人上门的概率(PSC、CRT),Ponero 兑换处开放后每天的概率;币的市值(房租的倍数);
|
||||
/// 现金要价占市值的比例(PSC、CRT 与 Ponero 分开);钓鱼执法的概率与镇压期间的加成。</summary>
|
||||
public const double HotEventChance = 0.35, HotPoneroChance = 0.05, HotValueMinRents = 4, HotValueMaxRents = 15;
|
||||
public const double HotCutMin = 0.45, HotCutMax = 0.60, HotPoneroCutMin = 0.70, HotPoneroCutMax = 0.80, HotSting = 0.05, HotStingCrackdown = 0.10;
|
||||
/// <summary>假客服:每天上门的概率;伪造转账:用币付款的顾客里是骗子的比例;两者都从第几天起。</summary>
|
||||
public const double FakeSupportChance = 0.04, FakeTransferShare = 0.08;
|
||||
public const int ScamMinDay = 10;
|
||||
|
||||
/// <summary>Web3 内置自动换币:商家不收手里的币时,按这个比例多付(DEX 手续费 0.3% 加上高滑点),省得自己去换。</summary>
|
||||
public const double BmAutoSwapSlip = 0.08;
|
||||
|
||||
/// <summary>剧情联动:塞尔皮科证据交给革命军(CRA 补贴池注资、螺旋概率倍率与期限、SPARK 几晚内涨到的倍数)、交给黑市(CRT 脱锚与被出卖的倍率)、
|
||||
/// 交给治安部(期限内出金审查命中、混币器制裁、操纵与内幕查处的倍率);埃莉诺泄露数据盘(CRC 托管减记倍率、SPARK 涨幅)、交回(CRC 脱锚倍率);
|
||||
/// 伦警官被捕(期限与查处倍率);SPARK 推涨分几晚走完。</summary>
|
||||
public const double StoryRevSubsidy = 10000, StoryCraSpiralMult = 0.5, StorySerpicoSpark = 1.2;
|
||||
public const double StoryBmCrtMult = 0.5;
|
||||
public const int StorySecDays = 30;
|
||||
public const double StorySecAmlMult = 1.5, StorySecSanctionMult = 1.5, StorySecEnforceMult = 1.3;
|
||||
public const double StoryLeakHaircutMult = 2, StoryLeakSpark = 1.15, StoryReturnCrcMult = 0.5;
|
||||
public const int StoryLunDays = 14, StorySparkNights = 5;
|
||||
/// <summary>混币器运营者 Tumbler:第几天起开始;帮他藏好密钥盘后的混币器手续费、匿名集倍率和谢礼(CRT);举报的赏金(信用点)和治安部声望;
|
||||
/// 卖给黑市得的 CRT(一半带污点)、黑市声望、之后混币器的手续费和跑路倍率;密钥盘的价值(违禁品,搜到按它记罪证)。</summary>
|
||||
public const int TumblerMinDay = 30;
|
||||
public const double TumblerKeptFee = 0.5, TumblerKeptVolume = 1.5, TumblerGift = 1000;
|
||||
public const int TumblerBounty = 1200, TumblerSecRep = 8, TumblerBmRep = 5;
|
||||
public const double TumblerSellCrt = 3000, TumblerSoldFee = 1.5, TumblerSoldRug = 4;
|
||||
public const int TumblerDriveValue = 600;
|
||||
public const double StoryLunMult = 1.3;
|
||||
|
||||
/// <summary>行情图的 NPC 成交量:每天的基础量占主池深度的比例(按币种),价格波动越大成交越多(|涨跌幅| × 倍数),再乘 0.6–1.4 的随机。</summary>
|
||||
public const double ChartVolPsc = 0.12, ChartVolCrc = 0.10, ChartVolCrt = 0.06, ChartVolCra = 0.04, ChartVolSpark = 0.03, ChartVolPonero = 0.01, ChartVolMove = 8;
|
||||
|
||||
/// <summary>主交易对(信用点一侧)的深度随天数增长。</summary>
|
||||
public static double PoolDepth(int day) => PoolDepth0 * (1 + day / 60.0);
|
||||
|
||||
/// <summary>永续的成交深度,同样随天数增长。</summary>
|
||||
public static double PerpDepth(int day) => PerpDepth0 * (1 + day / 60.0);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,494 @@
|
||||
// 由测试项目生成:dotnet run --project tests/Decentralized.Domain.Tests -c Release -- --gen-tuning-table
|
||||
// Tuning 增删数值后要重新生成(单元测试会核对)。
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
|
||||
namespace Decentralized.Domain
|
||||
{
|
||||
internal static class TuningTable
|
||||
{
|
||||
public static readonly Dictionary<string, double> Scalars = new Dictionary<string, double>
|
||||
{
|
||||
["AirdropChance"] = Tuning.AirdropChance,
|
||||
["AirdropDays"] = Tuning.AirdropDays,
|
||||
["AirdropDrainMax"] = Tuning.AirdropDrainMax,
|
||||
["AirdropDrainMin"] = Tuning.AirdropDrainMin,
|
||||
["AirdropRewardMax"] = Tuning.AirdropRewardMax,
|
||||
["AirdropRewardMin"] = Tuning.AirdropRewardMin,
|
||||
["AirdropScam"] = Tuning.AirdropScam,
|
||||
["AmlBigRents"] = Tuning.AmlBigRents,
|
||||
["AmlCumRents"] = Tuning.AmlCumRents,
|
||||
["AmlExcessWeight"] = Tuning.AmlExcessWeight,
|
||||
["AmlHeavyRatio"] = Tuning.AmlHeavyRatio,
|
||||
["AmlMaxChance"] = Tuning.AmlMaxChance,
|
||||
["AmlMixerBonus"] = Tuning.AmlMixerBonus,
|
||||
["AmlTaintMult"] = Tuning.AmlTaintMult,
|
||||
["AmlTaintRatio"] = Tuning.AmlTaintRatio,
|
||||
["AmlWindowDays"] = Tuning.AmlWindowDays,
|
||||
["AsicChance"] = Tuning.AsicChance,
|
||||
["AsicDeadValue"] = Tuning.AsicDeadValue,
|
||||
["AsicNewShare"] = Tuning.AsicNewShare,
|
||||
["AsicRepM1"] = Tuning.AsicRepM1,
|
||||
["AsicRepM2"] = Tuning.AsicRepM2,
|
||||
["AsicRepM3"] = Tuning.AsicRepM3,
|
||||
["AsicRepairHealthCut"] = Tuning.AsicRepairHealthCut,
|
||||
["AsicUsedHealthMax"] = Tuning.AsicUsedHealthMax,
|
||||
["AsicUsedHealthMin"] = Tuning.AsicUsedHealthMin,
|
||||
["AsicWeightM1"] = Tuning.AsicWeightM1,
|
||||
["AsicWeightM2"] = Tuning.AsicWeightM2,
|
||||
["AsicWeightM3"] = Tuning.AsicWeightM3,
|
||||
["BlockReward"] = Tuning.BlockReward,
|
||||
["BlocksPerDayMax"] = Tuning.BlocksPerDayMax,
|
||||
["BlocksPerDayMin"] = Tuning.BlocksPerDayMin,
|
||||
["BmAdvanceDiscount"] = Tuning.BmAdvanceDiscount,
|
||||
["BmAdvanceMinTrades"] = Tuning.BmAdvanceMinTrades,
|
||||
["BmAutoSwapSlip"] = Tuning.BmAutoSwapSlip,
|
||||
["BmBulk1Count"] = Tuning.BmBulk1Count,
|
||||
["BmBulk1Discount"] = Tuning.BmBulk1Discount,
|
||||
["BmBulk2Count"] = Tuning.BmBulk2Count,
|
||||
["BmBulk2Discount"] = Tuning.BmBulk2Discount,
|
||||
["BmBulkChance"] = Tuning.BmBulkChance,
|
||||
["BmBulkDays"] = Tuning.BmBulkDays,
|
||||
["BmBulkQtyMax"] = Tuning.BmBulkQtyMax,
|
||||
["BmBulkQtyMin"] = Tuning.BmBulkQtyMin,
|
||||
["BmCommission"] = Tuning.BmCommission,
|
||||
["BmControlled"] = Tuning.BmControlled,
|
||||
["BmCoreMerchants"] = Tuning.BmCoreMerchants,
|
||||
["BmDoorDays"] = Tuning.BmDoorDays,
|
||||
["BmEliteChance"] = Tuning.BmEliteChance,
|
||||
["BmEliteDays"] = Tuning.BmEliteDays,
|
||||
["BmEliteGpuChance"] = Tuning.BmEliteGpuChance,
|
||||
["BmEliteGpuTier"] = Tuning.BmEliteGpuTier,
|
||||
["BmEliteListings"] = Tuning.BmEliteListings,
|
||||
["BmEliteMinValue"] = Tuning.BmEliteMinValue,
|
||||
["BmEliteQtyMax"] = Tuning.BmEliteQtyMax,
|
||||
["BmEscrowFee"] = Tuning.BmEscrowFee,
|
||||
["BmFactorBulkMax"] = Tuning.BmFactorBulkMax,
|
||||
["BmFactorBulkMin"] = Tuning.BmFactorBulkMin,
|
||||
["BmFactorEliteMax"] = Tuning.BmFactorEliteMax,
|
||||
["BmFactorEliteMin"] = Tuning.BmFactorEliteMin,
|
||||
["BmFactorMax"] = Tuning.BmFactorMax,
|
||||
["BmFactorMin"] = Tuning.BmFactorMin,
|
||||
["BmFactorNewMax"] = Tuning.BmFactorNewMax,
|
||||
["BmFactorNewMin"] = Tuning.BmFactorNewMin,
|
||||
["BmFactorUsedMax"] = Tuning.BmFactorUsedMax,
|
||||
["BmFactorUsedMin"] = Tuning.BmFactorUsedMin,
|
||||
["BmFakeDetect"] = Tuning.BmFakeDetect,
|
||||
["BmForumRugFactor"] = Tuning.BmForumRugFactor,
|
||||
["BmForumScamHint"] = Tuning.BmForumScamHint,
|
||||
["BmFreshRatingMax"] = Tuning.BmFreshRatingMax,
|
||||
["BmFreshRatingMin"] = Tuning.BmFreshRatingMin,
|
||||
["BmFreshTradesMax"] = Tuning.BmFreshTradesMax,
|
||||
["BmGpuChance"] = Tuning.BmGpuChance,
|
||||
["BmGpuFake"] = Tuning.BmGpuFake,
|
||||
["BmGpuMarkup"] = Tuning.BmGpuMarkup,
|
||||
["BmGpuNew"] = Tuning.BmGpuNew,
|
||||
["BmHighRep"] = Tuning.BmHighRep,
|
||||
["BmHonestFresh"] = Tuning.BmHonestFresh,
|
||||
["BmHoneypotBase"] = Tuning.BmHoneypotBase,
|
||||
["BmHoneypotDays"] = Tuning.BmHoneypotDays,
|
||||
["BmHoneypotMax"] = Tuning.BmHoneypotMax,
|
||||
["BmHoneypotPerSecRep"] = Tuning.BmHoneypotPerSecRep,
|
||||
["BmInterceptCrackdown"] = Tuning.BmInterceptCrackdown,
|
||||
["BmInterceptDoor"] = Tuning.BmInterceptDoor,
|
||||
["BmListFee"] = Tuning.BmListFee,
|
||||
["BmMaxKinds"] = Tuning.BmMaxKinds,
|
||||
["BmMaxStack"] = Tuning.BmMaxStack,
|
||||
["BmMaxUnitValue"] = Tuning.BmMaxUnitValue,
|
||||
["BmMerchantCount"] = Tuning.BmMerchantCount,
|
||||
["BmMerchantListings"] = Tuning.BmMerchantListings,
|
||||
["BmMidRep"] = Tuning.BmMidRep,
|
||||
["BmNewGpuQtyMaxCut"] = Tuning.BmNewGpuQtyMaxCut,
|
||||
["BmNewGpuQtyMinCut"] = Tuning.BmNewGpuQtyMinCut,
|
||||
["BmOldRatingMax"] = Tuning.BmOldRatingMax,
|
||||
["BmOldRatingMin"] = Tuning.BmOldRatingMin,
|
||||
["BmOldTradesMax"] = Tuning.BmOldTradesMax,
|
||||
["BmOldTradesMin"] = Tuning.BmOldTradesMin,
|
||||
["BmOpenRep"] = Tuning.BmOpenRep,
|
||||
["BmPersonalCount"] = Tuning.BmPersonalCount,
|
||||
["BmPersonalEliteShare"] = Tuning.BmPersonalEliteShare,
|
||||
["BmPersonalFactorMax"] = Tuning.BmPersonalFactorMax,
|
||||
["BmPersonalFactorMin"] = Tuning.BmPersonalFactorMin,
|
||||
["BmPersonalGpuChance"] = Tuning.BmPersonalGpuChance,
|
||||
["BmPersonalGpuNew"] = Tuning.BmPersonalGpuNew,
|
||||
["BmPersonalListings"] = Tuning.BmPersonalListings,
|
||||
["BmPersonalQtyMax"] = Tuning.BmPersonalQtyMax,
|
||||
["BmPersonalScam"] = Tuning.BmPersonalScam,
|
||||
["BmPremium"] = Tuning.BmPremium,
|
||||
["BmPriceJitter"] = Tuning.BmPriceJitter,
|
||||
["BmQtyMax"] = Tuning.BmQtyMax,
|
||||
["BmQtyMin"] = Tuning.BmQtyMin,
|
||||
["BmRatingFakeLoss"] = Tuning.BmRatingFakeLoss,
|
||||
["BmRatingStart"] = Tuning.BmRatingStart,
|
||||
["BmRefreshDays"] = Tuning.BmRefreshDays,
|
||||
["BmRugBase"] = Tuning.BmRugBase,
|
||||
["BmRugClosedDays"] = Tuning.BmRugClosedDays,
|
||||
["BmRugMax"] = Tuning.BmRugMax,
|
||||
["BmRugPerTenK"] = Tuning.BmRugPerTenK,
|
||||
["BmSaleHold"] = Tuning.BmSaleHold,
|
||||
["BmSaleTaintChanceMax"] = Tuning.BmSaleTaintChanceMax,
|
||||
["BmSaleTaintChanceMin"] = Tuning.BmSaleTaintChanceMin,
|
||||
["BmSaleTaintRatioMax"] = Tuning.BmSaleTaintRatioMax,
|
||||
["BmSaleTaintRatioMin"] = Tuning.BmSaleTaintRatioMin,
|
||||
["BmScamFresh"] = Tuning.BmScamFresh,
|
||||
["BmScamOldRatingMax"] = Tuning.BmScamOldRatingMax,
|
||||
["BmScamOldRatingMin"] = Tuning.BmScamOldRatingMin,
|
||||
["BmScamSellerShare"] = Tuning.BmScamSellerShare,
|
||||
["BmSellDay1Mult"] = Tuning.BmSellDay1Mult,
|
||||
["BmSellDays1"] = Tuning.BmSellDays1,
|
||||
["BmSellDaysFast"] = Tuning.BmSellDaysFast,
|
||||
["BmSellDaysMax"] = Tuning.BmSellDaysMax,
|
||||
["BmSellFastMult"] = Tuning.BmSellFastMult,
|
||||
["BmSellMax"] = Tuning.BmSellMax,
|
||||
["BmSellMin"] = Tuning.BmSellMin,
|
||||
["BmSellerBust"] = Tuning.BmSellerBust,
|
||||
["BmSpotQtyMax"] = Tuning.BmSpotQtyMax,
|
||||
["BmStockBase"] = Tuning.BmStockBase,
|
||||
["BmStockPerRep"] = Tuning.BmStockPerRep,
|
||||
["BmTechChance"] = Tuning.BmTechChance,
|
||||
["BmTechMarkup"] = Tuning.BmTechMarkup,
|
||||
["BmTrapDelay"] = Tuning.BmTrapDelay,
|
||||
["BmTrapShare"] = Tuning.BmTrapShare,
|
||||
["BmTrapWindowCap"] = Tuning.BmTrapWindowCap,
|
||||
["BmUnlockPrice"] = Tuning.BmUnlockPrice,
|
||||
["BmVolumeRef"] = Tuning.BmVolumeRef,
|
||||
["BmVolumeTaintMax"] = Tuning.BmVolumeTaintMax,
|
||||
["BmWeightCra"] = Tuning.BmWeightCra,
|
||||
["BmWeightCrt"] = Tuning.BmWeightCrt,
|
||||
["BmWeightPonero"] = Tuning.BmWeightPonero,
|
||||
["BmWeightPsc"] = Tuning.BmWeightPsc,
|
||||
["BookAlpha"] = Tuning.BookAlpha,
|
||||
["BookK"] = Tuning.BookK,
|
||||
["CardBracketScratch"] = Tuning.CardBracketScratch,
|
||||
["CardFanChipped"] = Tuning.CardFanChipped,
|
||||
["CardFanDust"] = Tuning.CardFanDust,
|
||||
["CardFingersDark"] = Tuning.CardFingersDark,
|
||||
["CardFingersOxidized"] = Tuning.CardFingersOxidized,
|
||||
["CardHealthMax"] = Tuning.CardHealthMax,
|
||||
["CardHealthMin"] = Tuning.CardHealthMin,
|
||||
["CardSealMissing"] = Tuning.CardSealMissing,
|
||||
["CardValueFloor"] = Tuning.CardValueFloor,
|
||||
["ChartVolCra"] = Tuning.ChartVolCra,
|
||||
["ChartVolCrc"] = Tuning.ChartVolCrc,
|
||||
["ChartVolCrt"] = Tuning.ChartVolCrt,
|
||||
["ChartVolMove"] = Tuning.ChartVolMove,
|
||||
["ChartVolPonero"] = Tuning.ChartVolPonero,
|
||||
["ChartVolPsc"] = Tuning.ChartVolPsc,
|
||||
["ChartVolSpark"] = Tuning.ChartVolSpark,
|
||||
["CoinPayCra"] = Tuning.CoinPayCra,
|
||||
["CoinPayCrc"] = Tuning.CoinPayCrc,
|
||||
["CoinPayCrt"] = Tuning.CoinPayCrt,
|
||||
["CoinPayPremium"] = Tuning.CoinPayPremium,
|
||||
["CoinPayPsc"] = Tuning.CoinPayPsc,
|
||||
["CraC0"] = Tuning.CraC0,
|
||||
["CraCrMin"] = Tuning.CraCrMin,
|
||||
["CraCrStep"] = Tuning.CraCrStep,
|
||||
["CraCrashRatio"] = Tuning.CraCrashRatio,
|
||||
["CraDiscountMax"] = Tuning.CraDiscountMax,
|
||||
["CraEmbezzleMax"] = Tuning.CraEmbezzleMax,
|
||||
["CraEmbezzleMin"] = Tuning.CraEmbezzleMin,
|
||||
["CraLoot"] = Tuning.CraLoot,
|
||||
["CraMintDaysMax"] = Tuning.CraMintDaysMax,
|
||||
["CraMintDaysMin"] = Tuning.CraMintDaysMin,
|
||||
["CraNpcStake"] = Tuning.CraNpcStake,
|
||||
["CraRate"] = Tuning.CraRate,
|
||||
["CraRateLow"] = Tuning.CraRateLow,
|
||||
["CraRugPerDepeg"] = Tuning.CraRugPerDepeg,
|
||||
["CraS0"] = Tuning.CraS0,
|
||||
["CraSafeRatio"] = Tuning.CraSafeRatio,
|
||||
["CraSpiralWeekly"] = Tuning.CraSpiralWeekly,
|
||||
["CraSubsidyWarn"] = Tuning.CraSubsidyWarn,
|
||||
["CraUnlockDays"] = Tuning.CraUnlockDays,
|
||||
["CraWarnLeadMax"] = Tuning.CraWarnLeadMax,
|
||||
["CraWarnLeadMin"] = Tuning.CraWarnLeadMin,
|
||||
["CrcDepegChance"] = Tuning.CrcDepegChance,
|
||||
["CrcDepegDaysMax"] = Tuning.CrcDepegDaysMax,
|
||||
["CrcDepegDaysMin"] = Tuning.CrcDepegDaysMin,
|
||||
["CrcDepegMax"] = Tuning.CrcDepegMax,
|
||||
["CrcDepegMin"] = Tuning.CrcDepegMin,
|
||||
["CrcHaircut"] = Tuning.CrcHaircut,
|
||||
["CrcHaircutChance"] = Tuning.CrcHaircutChance,
|
||||
["CrimeEventCap"] = Tuning.CrimeEventCap,
|
||||
["CrtDepegChance"] = Tuning.CrtDepegChance,
|
||||
["CrtDepegDaysMax"] = Tuning.CrtDepegDaysMax,
|
||||
["CrtDepegDaysMin"] = Tuning.CrtDepegDaysMin,
|
||||
["CrtDepegMax"] = Tuning.CrtDepegMax,
|
||||
["CrtDepegMin"] = Tuning.CrtDepegMin,
|
||||
["CrtFreezeBase"] = Tuning.CrtFreezeBase,
|
||||
["CrtFreezePerRep"] = Tuning.CrtFreezePerRep,
|
||||
["CrtFreezeShare"] = Tuning.CrtFreezeShare,
|
||||
["CrtSwapFee"] = Tuning.CrtSwapFee,
|
||||
["CrtUnfreezeAfter"] = Tuning.CrtUnfreezeAfter,
|
||||
["CustomerSpotChance"] = Tuning.CustomerSpotChance,
|
||||
["CustomerSpotTierMismatch"] = Tuning.CustomerSpotTierMismatch,
|
||||
["DealerAdvanced"] = Tuning.DealerAdvanced,
|
||||
["DealerAdvancedFromDay"] = Tuning.DealerAdvancedFromDay,
|
||||
["DealerAdvancedSecond"] = Tuning.DealerAdvancedSecond,
|
||||
["DealerFlagship"] = Tuning.DealerFlagship,
|
||||
["DealerFlagshipFromDay"] = Tuning.DealerFlagshipFromDay,
|
||||
["DealerRigRestock"] = Tuning.DealerRigRestock,
|
||||
["DealerSpecialFlagshipFromDay"] = Tuning.DealerSpecialFlagshipFromDay,
|
||||
["DeathBase"] = Tuning.DeathBase,
|
||||
["DeathWorn"] = Tuning.DeathWorn,
|
||||
["DexFee"] = Tuning.DexFee,
|
||||
["ElecPrice"] = Tuning.ElecPrice,
|
||||
["EraKjMult"] = Tuning.EraKjMult,
|
||||
["EraMax"] = Tuning.EraMax,
|
||||
["EraMin"] = Tuning.EraMin,
|
||||
["EraWarnMax"] = Tuning.EraWarnMax,
|
||||
["EraWarnMin"] = Tuning.EraWarnMin,
|
||||
["ExchangeFee"] = Tuning.ExchangeFee,
|
||||
["FakeDeathFactor"] = Tuning.FakeDeathFactor,
|
||||
["FakeSignChance"] = Tuning.FakeSignChance,
|
||||
["FakeSupportChance"] = Tuning.FakeSupportChance,
|
||||
["FakeTransferShare"] = Tuning.FakeTransferShare,
|
||||
["FundsBaseSecs"] = Tuning.FundsBaseSecs,
|
||||
["FundsConfSecs"] = Tuning.FundsConfSecs,
|
||||
["HalvingDays"] = Tuning.HalvingDays,
|
||||
["HalvingPassMax"] = Tuning.HalvingPassMax,
|
||||
["HalvingPassMin"] = Tuning.HalvingPassMin,
|
||||
["HalvingRamp"] = Tuning.HalvingRamp,
|
||||
["HalvingRampDays"] = Tuning.HalvingRampDays,
|
||||
["HotCutMax"] = Tuning.HotCutMax,
|
||||
["HotCutMin"] = Tuning.HotCutMin,
|
||||
["HotEventChance"] = Tuning.HotEventChance,
|
||||
["HotPoneroChance"] = Tuning.HotPoneroChance,
|
||||
["HotPoneroCutMax"] = Tuning.HotPoneroCutMax,
|
||||
["HotPoneroCutMin"] = Tuning.HotPoneroCutMin,
|
||||
["HotSting"] = Tuning.HotSting,
|
||||
["HotStingCrackdown"] = Tuning.HotStingCrackdown,
|
||||
["HotValueMaxRents"] = Tuning.HotValueMaxRents,
|
||||
["HotValueMinRents"] = Tuning.HotValueMinRents,
|
||||
["IntelBriefPrice"] = Tuning.IntelBriefPrice,
|
||||
["IntelFake"] = Tuning.IntelFake,
|
||||
["IntelRep"] = Tuning.IntelRep,
|
||||
["LedgerMax"] = Tuning.LedgerMax,
|
||||
["LedgerShow"] = Tuning.LedgerShow,
|
||||
["ManipBase"] = Tuning.ManipBase,
|
||||
["ManipFree"] = Tuning.ManipFree,
|
||||
["ManipFreezeDays"] = Tuning.ManipFreezeDays,
|
||||
["ManipMax"] = Tuning.ManipMax,
|
||||
["ManipSlope"] = Tuning.ManipSlope,
|
||||
["MixerCleanRate"] = Tuning.MixerCleanRate,
|
||||
["MixerFee"] = Tuning.MixerFee,
|
||||
["MixerMaxRounds"] = Tuning.MixerMaxRounds,
|
||||
["MixerMin"] = Tuning.MixerMin,
|
||||
["MixerNpcVolume"] = Tuning.MixerNpcVolume,
|
||||
["MixerRugChance"] = Tuning.MixerRugChance,
|
||||
["MixerSanctionChance"] = Tuning.MixerSanctionChance,
|
||||
["MixerSanctionDays"] = Tuning.MixerSanctionDays,
|
||||
["MixerUnlockPrice"] = Tuning.MixerUnlockPrice,
|
||||
["ModuleHashCap"] = Tuning.ModuleHashCap,
|
||||
["ModuleKjCap"] = Tuning.ModuleKjCap,
|
||||
["ModuleRatio"] = Tuning.ModuleRatio,
|
||||
["ModuleWearCap"] = Tuning.ModuleWearCap,
|
||||
["NpcAdj"] = Tuning.NpcAdj,
|
||||
["NpcHash0"] = Tuning.NpcHash0,
|
||||
["NpcKjPerH"] = Tuning.NpcKjPerH,
|
||||
["NpcTargetRatio"] = Tuning.NpcTargetRatio,
|
||||
["PerpAdlHaircut"] = Tuning.PerpAdlHaircut,
|
||||
["PerpBanDays"] = Tuning.PerpBanDays,
|
||||
["PerpDebtDays"] = Tuning.PerpDebtDays,
|
||||
["PerpDebtInterest"] = Tuning.PerpDebtInterest,
|
||||
["PerpDepth0"] = Tuning.PerpDepth0,
|
||||
["PerpDepthMult"] = Tuning.PerpDepthMult,
|
||||
["PerpFee"] = Tuning.PerpFee,
|
||||
["PerpFeeToFund"] = Tuning.PerpFeeToFund,
|
||||
["PerpFund0"] = Tuning.PerpFund0,
|
||||
["PerpFundCap"] = Tuning.PerpFundCap,
|
||||
["PerpFundCoef"] = Tuning.PerpFundCoef,
|
||||
["PerpLiqFee"] = Tuning.PerpLiqFee,
|
||||
["PerpMaint"] = Tuning.PerpMaint,
|
||||
["PerpNewsMove"] = Tuning.PerpNewsMove,
|
||||
["PerpNpcAvgPos"] = Tuning.PerpNpcAvgPos,
|
||||
["PerpNpcBankBase"] = Tuning.PerpNpcBankBase,
|
||||
["PerpNpcBankFree"] = Tuning.PerpNpcBankFree,
|
||||
["PerpNpcBankMax"] = Tuning.PerpNpcBankMax,
|
||||
["PerpNpcBankSlope"] = Tuning.PerpNpcBankSlope,
|
||||
["PerpNpcGap"] = Tuning.PerpNpcGap,
|
||||
["PerpNpcLeft"] = Tuning.PerpNpcLeft,
|
||||
["PerpNpcLiqScale"] = Tuning.PerpNpcLiqScale,
|
||||
["PerpNpcOi"] = Tuning.PerpNpcOi,
|
||||
["PerpOpenBuffer"] = Tuning.PerpOpenBuffer,
|
||||
["PerpPscCap"] = Tuning.PerpPscCap,
|
||||
["PerpPscLev"] = Tuning.PerpPscLev,
|
||||
["PerpSparkCap"] = Tuning.PerpSparkCap,
|
||||
["PerpSparkLev"] = Tuning.PerpSparkLev,
|
||||
["PoinSparkDepthShare"] = Tuning.PoinSparkDepthShare,
|
||||
["PoneroDailyCap"] = Tuning.PoneroDailyCap,
|
||||
["PoneroFee"] = Tuning.PoneroFee,
|
||||
["PoneroOpenRep"] = Tuning.PoneroOpenRep,
|
||||
["PoneroPscRatio"] = Tuning.PoneroPscRatio,
|
||||
["PonziAdCost"] = Tuning.PonziAdCost,
|
||||
["PonziBase0"] = Tuning.PonziBase0,
|
||||
["PonziBasePerDay"] = Tuning.PonziBasePerDay,
|
||||
["PonziCap0"] = Tuning.PonziCap0,
|
||||
["PonziCapPerDay"] = Tuning.PonziCapPerDay,
|
||||
["PonziCrime"] = Tuning.PonziCrime,
|
||||
["PonziMinDay"] = Tuning.PonziMinDay,
|
||||
["PonziRateExp"] = Tuning.PonziRateExp,
|
||||
["PonziReport0"] = Tuning.PonziReport0,
|
||||
["PonziReportRate"] = Tuning.PonziReportRate,
|
||||
["PonziReportSize"] = Tuning.PonziReportSize,
|
||||
["PonziWithdraw"] = Tuning.PonziWithdraw,
|
||||
["PoolDepth0"] = Tuning.PoolDepth0,
|
||||
["PoolFee"] = Tuning.PoolFee,
|
||||
["PredictCap"] = Tuning.PredictCap,
|
||||
["PredictDepth"] = Tuning.PredictDepth,
|
||||
["PredictDrift"] = Tuning.PredictDrift,
|
||||
["PredictFactionDaily"] = Tuning.PredictFactionDaily,
|
||||
["PredictFee"] = Tuning.PredictFee,
|
||||
["PredictFraudCap"] = Tuning.PredictFraudCap,
|
||||
["PredictFraudShare"] = Tuning.PredictFraudShare,
|
||||
["PredictGasBlind"] = Tuning.PredictGasBlind,
|
||||
["PredictHistory"] = Tuning.PredictHistory,
|
||||
["PredictInsiderCatch"] = Tuning.PredictInsiderCatch,
|
||||
["PredictInsiderShare"] = Tuning.PredictInsiderShare,
|
||||
["PredictLoss0"] = Tuning.PredictLoss0,
|
||||
["PredictLossPerDay"] = Tuning.PredictLossPerDay,
|
||||
["PredictMoveLog"] = Tuning.PredictMoveLog,
|
||||
["PredictNewPerDay"] = Tuning.PredictNewPerDay,
|
||||
["PredictNoise"] = Tuning.PredictNoise,
|
||||
["PredictOpenMax"] = Tuning.PredictOpenMax,
|
||||
["PredictOpenMin"] = Tuning.PredictOpenMin,
|
||||
["PredictPMax"] = Tuning.PredictPMax,
|
||||
["PredictPMin"] = Tuning.PredictPMin,
|
||||
["PredictUnlockDay"] = Tuning.PredictUnlockDay,
|
||||
["PriceCeiling"] = Tuning.PriceCeiling,
|
||||
["PriceFloor"] = Tuning.PriceFloor,
|
||||
["PscStartPrice"] = Tuning.PscStartPrice,
|
||||
["PscVol"] = Tuning.PscVol,
|
||||
["RefurbishHealth"] = Tuning.RefurbishHealth,
|
||||
["RepLossMax"] = Tuning.RepLossMax,
|
||||
["Revert"] = Tuning.Revert,
|
||||
["RigKj"] = Tuning.RigKj,
|
||||
["RigPrice"] = Tuning.RigPrice,
|
||||
["ScamMinDay"] = Tuning.ScamMinDay,
|
||||
["SentimentKappa"] = Tuning.SentimentKappa,
|
||||
["SentimentVol"] = Tuning.SentimentVol,
|
||||
["SideArbRate"] = Tuning.SideArbRate,
|
||||
["SideDepthShare"] = Tuning.SideDepthShare,
|
||||
["SparkDepthShare"] = Tuning.SparkDepthShare,
|
||||
["SparkFee"] = Tuning.SparkFee,
|
||||
["SparkMaxMult"] = Tuning.SparkMaxMult,
|
||||
["SparkMinMult"] = Tuning.SparkMinMult,
|
||||
["SparkRaidShock"] = Tuning.SparkRaidShock,
|
||||
["SparkRevert"] = Tuning.SparkRevert,
|
||||
["SparkStart"] = Tuning.SparkStart,
|
||||
["SparkUnrestShock"] = Tuning.SparkUnrestShock,
|
||||
["SparkVol"] = Tuning.SparkVol,
|
||||
["StableAmp"] = Tuning.StableAmp,
|
||||
["StableAmpBroken"] = Tuning.StableAmpBroken,
|
||||
["StableAmpDepeg"] = Tuning.StableAmpDepeg,
|
||||
["StableBrokenBand"] = Tuning.StableBrokenBand,
|
||||
["StableBrokenDepth"] = Tuning.StableBrokenDepth,
|
||||
["StableDepegBand"] = Tuning.StableDepegBand,
|
||||
["StableFee"] = Tuning.StableFee,
|
||||
["StoryBmCrtMult"] = Tuning.StoryBmCrtMult,
|
||||
["StoryCraSpiralMult"] = Tuning.StoryCraSpiralMult,
|
||||
["StoryLeakHaircutMult"] = Tuning.StoryLeakHaircutMult,
|
||||
["StoryLeakSpark"] = Tuning.StoryLeakSpark,
|
||||
["StoryLunDays"] = Tuning.StoryLunDays,
|
||||
["StoryLunMult"] = Tuning.StoryLunMult,
|
||||
["StoryReturnCrcMult"] = Tuning.StoryReturnCrcMult,
|
||||
["StoryRevSubsidy"] = Tuning.StoryRevSubsidy,
|
||||
["StorySecAmlMult"] = Tuning.StorySecAmlMult,
|
||||
["StorySecDays"] = Tuning.StorySecDays,
|
||||
["StorySecEnforceMult"] = Tuning.StorySecEnforceMult,
|
||||
["StorySecSanctionMult"] = Tuning.StorySecSanctionMult,
|
||||
["StorySerpicoSpark"] = Tuning.StorySerpicoSpark,
|
||||
["StorySparkNights"] = Tuning.StorySparkNights,
|
||||
["SupplyAdjust"] = Tuning.SupplyAdjust,
|
||||
["TaxRate"] = Tuning.TaxRate,
|
||||
["TumblerBmRep"] = Tuning.TumblerBmRep,
|
||||
["TumblerBounty"] = Tuning.TumblerBounty,
|
||||
["TumblerDriveValue"] = Tuning.TumblerDriveValue,
|
||||
["TumblerGift"] = Tuning.TumblerGift,
|
||||
["TumblerKeptFee"] = Tuning.TumblerKeptFee,
|
||||
["TumblerKeptVolume"] = Tuning.TumblerKeptVolume,
|
||||
["TumblerMinDay"] = Tuning.TumblerMinDay,
|
||||
["TumblerSecRep"] = Tuning.TumblerSecRep,
|
||||
["TumblerSellCrt"] = Tuning.TumblerSellCrt,
|
||||
["TumblerSoldFee"] = Tuning.TumblerSoldFee,
|
||||
["TumblerSoldRug"] = Tuning.TumblerSoldRug,
|
||||
["TxConfirmBase"] = Tuning.TxConfirmBase,
|
||||
["TxConfirmBig"] = Tuning.TxConfirmBig,
|
||||
["TxConfirmBigValue"] = Tuning.TxConfirmBigValue,
|
||||
["TxConfirmMid"] = Tuning.TxConfirmMid,
|
||||
["TxConfirmMidValue"] = Tuning.TxConfirmMidValue,
|
||||
["TxCongestedFeeMult"] = Tuning.TxCongestedFeeMult,
|
||||
["TxCongestedNormalSlow"] = Tuning.TxCongestedNormalSlow,
|
||||
["TxCongestedSlowSlow"] = Tuning.TxCongestedSlowSlow,
|
||||
["TxCongestionChance"] = Tuning.TxCongestionChance,
|
||||
["TxCongestionDaysMax"] = Tuning.TxCongestionDaysMax,
|
||||
["TxFeeFast"] = Tuning.TxFeeFast,
|
||||
["TxFeeNormal"] = Tuning.TxFeeNormal,
|
||||
["TxFeeSlow"] = Tuning.TxFeeSlow,
|
||||
["TxGasAmp"] = Tuning.TxGasAmp,
|
||||
["TxGasNoise"] = Tuning.TxGasNoise,
|
||||
["TxGasPeriod"] = Tuning.TxGasPeriod,
|
||||
["TxHijackChance"] = Tuning.TxHijackChance,
|
||||
["TxHoldSecs"] = Tuning.TxHoldSecs,
|
||||
["TxPhishChance"] = Tuning.TxPhishChance,
|
||||
["TxPoisonChance"] = Tuning.TxPoisonChance,
|
||||
["TxPoisonDelayMax"] = Tuning.TxPoisonDelayMax,
|
||||
["TxSlowDrop"] = Tuning.TxSlowDrop,
|
||||
["TxSpeedFast"] = Tuning.TxSpeedFast,
|
||||
["TxSpeedNormal"] = Tuning.TxSpeedNormal,
|
||||
["TxSpeedSlow"] = Tuning.TxSpeedSlow,
|
||||
["UnlockPrice"] = Tuning.UnlockPrice,
|
||||
["UsedFakeMiddleman"] = Tuning.UsedFakeMiddleman,
|
||||
["UsedFakeScammer"] = Tuning.UsedFakeScammer,
|
||||
["UsedFirstDay"] = Tuning.UsedFirstDay,
|
||||
["UsedMiddlemanHide"] = Tuning.UsedMiddlemanHide,
|
||||
["UsedMiddlemanMarkup"] = Tuning.UsedMiddlemanMarkup,
|
||||
["UsedMiddlemanShare"] = Tuning.UsedMiddlemanShare,
|
||||
["UsedScamBase"] = Tuning.UsedScamBase,
|
||||
["UsedScamMax"] = Tuning.UsedScamMax,
|
||||
["UsedScamPerDay"] = Tuning.UsedScamPerDay,
|
||||
["UsedVisitChance"] = Tuning.UsedVisitChance,
|
||||
["WalletDrainFull"] = Tuning.WalletDrainFull,
|
||||
["WalletDrainMin"] = Tuning.WalletDrainMin,
|
||||
["WalletDrainSlowDays"] = Tuning.WalletDrainSlowDays,
|
||||
["WalletJacksonChance"] = Tuning.WalletJacksonChance,
|
||||
["WalletJacksonPrice"] = Tuning.WalletJacksonPrice,
|
||||
["WalletMallChance"] = Tuning.WalletMallChance,
|
||||
["WalletMallMax"] = Tuning.WalletMallMax,
|
||||
["WalletMallMin"] = Tuning.WalletMallMin,
|
||||
["WalletMallQtyMax"] = Tuning.WalletMallQtyMax,
|
||||
["WalletMax"] = Tuning.WalletMax,
|
||||
["WalletPoisonShare"] = Tuning.WalletPoisonShare,
|
||||
["WhaleMax"] = Tuning.WhaleMax,
|
||||
["WhaleMin"] = Tuning.WhaleMin,
|
||||
["WickChance"] = Tuning.WickChance,
|
||||
["WickMax"] = Tuning.WickMax,
|
||||
["WickMin"] = Tuning.WickMin,
|
||||
["WickReal"] = Tuning.WickReal,
|
||||
["WickRevertMax"] = Tuning.WickRevertMax,
|
||||
["WickRevertMin"] = Tuning.WickRevertMin,
|
||||
["YieldCap0"] = Tuning.YieldCap0,
|
||||
["YieldCapPerDay"] = Tuning.YieldCapPerDay,
|
||||
["YieldLockDays"] = Tuning.YieldLockDays,
|
||||
["YieldPoolChance"] = Tuning.YieldPoolChance,
|
||||
["YieldPoolMax"] = Tuning.YieldPoolMax,
|
||||
["YieldReserveDays"] = Tuning.YieldReserveDays,
|
||||
["YieldRugNightly"] = Tuning.YieldRugNightly,
|
||||
["YieldScamAudit"] = Tuning.YieldScamAudit,
|
||||
["YieldScamTimelock"] = Tuning.YieldScamTimelock,
|
||||
};
|
||||
|
||||
public static readonly Dictionary<string, double[]> Arrays = new Dictionary<string, double[]>
|
||||
{
|
||||
["BmSellMults"] = Array.ConvertAll(Tuning.BmSellMults, v => (double)v),
|
||||
["CraSpiralPath"] = Array.ConvertAll(Tuning.CraSpiralPath, v => (double)v),
|
||||
["IntelTipAcc"] = Array.ConvertAll(Tuning.IntelTipAcc, v => (double)v),
|
||||
["IntelTipPrice"] = Array.ConvertAll(Tuning.IntelTipPrice, v => (double)v),
|
||||
["PonziRates"] = Array.ConvertAll(Tuning.PonziRates, v => (double)v),
|
||||
["SparkSpiralPath"] = Array.ConvertAll(Tuning.SparkSpiralPath, v => (double)v),
|
||||
["UsedHealthMax"] = Array.ConvertAll(Tuning.UsedHealthMax, v => (double)v),
|
||||
["UsedHealthMin"] = Array.ConvertAll(Tuning.UsedHealthMin, v => (double)v),
|
||||
["YieldRates"] = Array.ConvertAll(Tuning.YieldRates, v => (double)v),
|
||||
["YieldScamByRate"] = Array.ConvertAll(Tuning.YieldScamByRate, v => (double)v),
|
||||
};
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,53 @@
|
||||
using System;
|
||||
using System.Globalization;
|
||||
using System.Text.RegularExpressions;
|
||||
|
||||
namespace Decentralized.Domain
|
||||
{
|
||||
/// <summary>
|
||||
/// 文本里的数值占位符:<c>{Name}</c>、<c>{Name:%}</c>、<c>{Name[2]:%}</c>,也可以走嵌套类 <c>{Section.Name}</c>。
|
||||
/// 手册等说明文字不直接写数字,渲染时从 <see cref="Tuning"/> 取值,数值一改文字跟着变。
|
||||
/// <c>%</c> 把小数按百分比显示(0.03 → 3%),<c>+%</c> 把倍数显示成涨幅(1.2 → 20%);不带格式时去掉多余的零。
|
||||
/// </summary>
|
||||
public static class TuningText
|
||||
{
|
||||
private static readonly Regex Placeholder = new Regex(@"\{([A-Za-z0-9_.]+)(?:\[(\d+)\])?(?::(\+?%))?\}", RegexOptions.Compiled);
|
||||
|
||||
public static string Render(string text)
|
||||
{
|
||||
if (string.IsNullOrEmpty(text)) return text;
|
||||
return Placeholder.Replace(text, m => TryValue(m.Groups[1].Value, m.Groups[2].Success ? int.Parse(m.Groups[2].Value) : -1, out var v)
|
||||
? Format(v, m.Groups[3].Value)
|
||||
: m.Value);
|
||||
}
|
||||
|
||||
/// <summary>文本里取不到值的占位符(测试用)。</summary>
|
||||
public static System.Collections.Generic.List<string> Unresolved(string text)
|
||||
{
|
||||
var bad = new System.Collections.Generic.List<string>();
|
||||
foreach (Match m in Placeholder.Matches(text ?? ""))
|
||||
if (!TryValue(m.Groups[1].Value, m.Groups[2].Success ? int.Parse(m.Groups[2].Value) : -1, out _)) bad.Add(m.Value);
|
||||
return bad;
|
||||
}
|
||||
|
||||
private static string Format(double v, string format)
|
||||
{
|
||||
bool percent = format == "%" || format == "+%";
|
||||
if (format == "+%") v -= 1; // 倍数 1.2 → 20%
|
||||
if (percent) v *= 100;
|
||||
return Math.Round(v, 4).ToString("0.####", CultureInfo.InvariantCulture) + (percent ? "%" : "");
|
||||
}
|
||||
|
||||
private static bool TryValue(string path, int index, out double value)
|
||||
{
|
||||
value = 0;
|
||||
if (TuningTable.Arrays.TryGetValue(path, out var arr))
|
||||
{
|
||||
if (index < 0 || index >= arr.Length) return false;
|
||||
value = arr[index];
|
||||
return true;
|
||||
}
|
||||
return index < 0 && TuningTable.Scalars.TryGetValue(path, out value);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,55 @@
|
||||
using System.Collections.Generic;
|
||||
|
||||
namespace Decentralized.Domain
|
||||
{
|
||||
/// <summary>钱包里的一条转账记录:对方地址、币种、数量、哪天、转入还是转出。地址投毒的 0 币转入也记在这里。</summary>
|
||||
public sealed class TxRecord
|
||||
{
|
||||
public string Addr, Asset;
|
||||
public double Amount;
|
||||
public int Day;
|
||||
public bool In;
|
||||
}
|
||||
|
||||
/// <summary>手续费档位:慢最便宜,网络拥堵时可能被挤出内存池;快最贵,拥堵时也照常确认。</summary>
|
||||
public enum FeeTier { Slow, Normal, Fast }
|
||||
|
||||
/// <summary>链上转账的规则:手续费、需要的确认数、拥堵时慢档被丢弃的概率。</summary>
|
||||
public static class TxRules
|
||||
{
|
||||
/// <summary>手续费(信用点等值,按转出的币扣):档位基础价 × 拥堵倍数。</summary>
|
||||
public static double FeeCredits(FeeTier t, bool congested, double gas = 1) =>
|
||||
(t == FeeTier.Slow ? Tuning.TxFeeSlow : t == FeeTier.Normal ? Tuning.TxFeeNormal : Tuning.TxFeeFast) * gas * (congested ? Tuning.TxCongestedFeeMult : 1);
|
||||
|
||||
/// <summary>Gas 周期部分:phase 是这一局的起始相位(0..周期-1)。</summary>
|
||||
public static double GasCycle(int day, int phase) => 1 + Tuning.TxGasAmp * System.Math.Sin(2 * System.Math.PI * (day + phase) / Tuning.TxGasPeriod);
|
||||
|
||||
/// <summary>某天的 gas 指数:周期 × (1 ± 随机波动)。</summary>
|
||||
public static double Gas(int day, int phase, Rng rng) => GasCycle(day, phase) * (1 + Tuning.TxGasNoise * (rng.NextDouble() * 2 - 1));
|
||||
|
||||
/// <summary>需要的确认数:金额越大越多。</summary>
|
||||
public static int Confirmations(double valueCredits) =>
|
||||
valueCredits >= Tuning.TxConfirmBigValue ? Tuning.TxConfirmBig : valueCredits >= Tuning.TxConfirmMidValue ? Tuning.TxConfirmMid : Tuning.TxConfirmBase;
|
||||
|
||||
/// <summary>Gas 档位本身的速度倍数:越高越快。</summary>
|
||||
public static double TierSpeed(FeeTier t) => t == FeeTier.Fast ? Tuning.TxSpeedFast : t == FeeTier.Normal ? Tuning.TxSpeedNormal : Tuning.TxSpeedSlow;
|
||||
|
||||
/// <summary>整条确认时间线的时间倍数:档位速度 × 拥堵时慢档、普通档变慢(快档不受拥堵影响)。</summary>
|
||||
public static double Slowdown(FeeTier t, bool congested) => TierSpeed(t) * (!congested ? 1 : t == FeeTier.Fast ? 1 : t == FeeTier.Normal ? Tuning.TxCongestedNormalSlow : Tuning.TxCongestedSlowSlow);
|
||||
|
||||
/// <summary>拥堵时慢档交易被挤出内存池的概率(交易作废,手续费照扣)。</summary>
|
||||
public static double DropChance(FeeTier t, bool congested) => congested && t == FeeTier.Slow ? Tuning.TxSlowDrop : 0;
|
||||
|
||||
/// <summary>夜间区块高度的自然增长。</summary>
|
||||
public static int BlocksPerDay(Rng rng) => rng.Range(Tuning.BlocksPerDayMin, Tuning.BlocksPerDayMax);
|
||||
|
||||
/// <summary>转账记录最多保留几条。</summary>
|
||||
public const int HistoryMax = 20;
|
||||
|
||||
public static void Record(List<TxRecord> history, TxRecord r)
|
||||
{
|
||||
history.Insert(0, r);
|
||||
if (history.Count > HistoryMax) history.RemoveRange(HistoryMax, history.Count - HistoryMax);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,64 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
|
||||
namespace Decentralized.Domain
|
||||
{
|
||||
/// <summary>二手显卡贩子的类型:老实人按真实价卖;中间商加价;骗子夹带假卡,按标称型号的价卖。</summary>
|
||||
public enum DealerKind { Honest, Middleman, Scammer }
|
||||
|
||||
/// <summary>贩子带来的一张卡:型号、健康度、是不是假卡。怎么说由 <see cref="CardLabels.DealerClaim"/> 决定,中间商另加 <see cref="MarkupPct"/>% 的价。</summary>
|
||||
public sealed class UsedCard
|
||||
{
|
||||
public string Model;
|
||||
public string FakeOf;
|
||||
public double Health;
|
||||
public int MarkupPct;
|
||||
}
|
||||
|
||||
public static class UsedDealers
|
||||
{
|
||||
public const double MiddlemanMarkup = Tuning.UsedMiddlemanMarkup;
|
||||
public const double FakeShareMiddleman = Tuning.UsedFakeMiddleman, FakeShareScammer = Tuning.UsedFakeScammer;
|
||||
|
||||
/// <summary>今天来的贩子的类型:骗子越往后越多。</summary>
|
||||
public static DealerKind Kind(int day, Rng rng)
|
||||
{
|
||||
double scam = Scales.R(Math.Min(Tuning.UsedScamMax, Tuning.UsedScamBase + day * Tuning.UsedScamPerDay));
|
||||
double r = rng.NextDouble();
|
||||
return r < scam ? DealerKind.Scammer : r < scam + Tuning.UsedMiddlemanShare ? DealerKind.Middleman : DealerKind.Honest;
|
||||
}
|
||||
|
||||
/// <summary>能出现在二手市场上的型号:按天数放开,旗舰第 30 天起。</summary>
|
||||
public static string[] Pool(int day)
|
||||
{
|
||||
var list = new List<string>(Dealer.Basic);
|
||||
if (day >= Dealer.AdvancedFromDay) list.AddRange(Dealer.Advanced);
|
||||
if (day >= Dealer.FlagshipFromDay) list.AddRange(Dealer.Flagship);
|
||||
return list.ToArray();
|
||||
}
|
||||
|
||||
/// <summary>从池里抽一张:随机型号与成色;按 fakeShare 的概率是假卡(背后是便宜得多的真实芯片,废片只给低档标称)。</summary>
|
||||
public static UsedCard Card(string[] pool, double fakeShare, int markupPct, Rng rng, double minHealth = Tuning.CardHealthMin, double maxHealth = Tuning.CardHealthMax)
|
||||
{
|
||||
var label = pool[rng.Range(0, pool.Length - 1)];
|
||||
var card = new UsedCard { Model = label, Health = minHealth + rng.NextDouble() * (maxHealth - minHealth), MarkupPct = markupPct };
|
||||
var cheaper = Hardware.Specs.Values.Where(s => !s.Asic && s.Price * 2 <= Hardware.Specs[label].Price && (!s.Scrap || Hardware.Specs[label].Tier == 0)).Select(s => s.Model).ToArray();
|
||||
if (cheaper.Length > 0 && rng.Chance(fakeShare)) card.FakeOf = cheaper[rng.Range(0, cheaper.Length - 1)];
|
||||
return card;
|
||||
}
|
||||
|
||||
public static List<UsedCard> Cards(DealerKind kind, int day, Rng rng)
|
||||
{
|
||||
var pool = Pool(day);
|
||||
int count = rng.Range(3, 5);
|
||||
var cards = new List<UsedCard>();
|
||||
for (int i = 0; i < count; i++)
|
||||
{
|
||||
double share = kind == DealerKind.Scammer ? FakeShareScammer : kind == DealerKind.Middleman ? FakeShareMiddleman : 0;
|
||||
cards.Add(Card(pool, share, kind == DealerKind.Middleman ? (int)Math.Round(MiddlemanMarkup * 100) : 0, rng, Tuning.UsedHealthMin[(int)kind], Tuning.UsedHealthMax[(int)kind]));
|
||||
}
|
||||
return cards;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -18,12 +18,89 @@ namespace Decentralized.Domain
|
||||
public double Basis;
|
||||
/// <summary>被执法标记。</summary>
|
||||
public bool Flagged;
|
||||
/// <summary>钱包编号("钱包 n"),添加时定下,销毁别的钱包也不变。</summary>
|
||||
public string Name;
|
||||
/// <summary>玩家起的名字;空时用默认名。</summary>
|
||||
public string Label;
|
||||
/// <summary>转账记录(最新的在前),PLEDGER 发送页的"最近"列表从这里取。</summary>
|
||||
public List<TxRecord> History = new List<TxRecord>();
|
||||
|
||||
/// <summary>硬件钱包被动过手脚(供应链投毒):别人手里有助记词。玩家看不到。</summary>
|
||||
public bool Poisoned;
|
||||
|
||||
/// <summary>被投毒的钱包被转空前的期望天数:门槛处 7 天,按价值线性降到满额处 1 天;不到门槛不会被转。</summary>
|
||||
public static double DrainDays(double value)
|
||||
{
|
||||
double t = Math.Min(1, (value - Tuning.WalletDrainMin) / (Tuning.WalletDrainFull - Tuning.WalletDrainMin));
|
||||
return Tuning.WalletDrainSlowDays - (Tuning.WalletDrainSlowDays - 1) * t;
|
||||
}
|
||||
|
||||
/// <summary>被投毒的钱包今晚被转空的概率 = 1 / 期望天数(每晚独立掷一次)。</summary>
|
||||
public static double DrainChance(double value) => value < Tuning.WalletDrainMin ? 0 : 1 / DrainDays(value);
|
||||
|
||||
/// <summary>转空:全部余额(含冻结的)连同污点、成本一起转走,返回转走的价值(信用点)。</summary>
|
||||
public double Drain(Func<string, double> price)
|
||||
{
|
||||
double v = Value(price);
|
||||
Balances.Clear(); Frozen.Clear(); FrozenUntil.Clear(); BuyQty.Clear(); BuyCost.Clear();
|
||||
Taint = 0; Basis = 0;
|
||||
return v;
|
||||
}
|
||||
|
||||
/// <summary>买入记录:每种币买入的数量与花费(信用点等值),用来显示买入均价。卖出或转出时按比例减少。</summary>
|
||||
public Dictionary<string, double> BuyQty = new Dictionary<string, double>(), BuyCost = new Dictionary<string, double>();
|
||||
|
||||
public void RecordBuy(string asset, double qty, double costCredits)
|
||||
{
|
||||
if (qty <= 0) return;
|
||||
BuyQty[asset] = (BuyQty.TryGetValue(asset, out var q) ? q : 0) + qty;
|
||||
BuyCost[asset] = (BuyCost.TryGetValue(asset, out var c) ? c : 0) + Math.Max(0, costCredits);
|
||||
}
|
||||
|
||||
/// <summary>买入均价(信用点);没有买入记录(例如全是挖出来的)返回 null。</summary>
|
||||
public double? AvgBuy(string asset) => BuyQty.TryGetValue(asset, out var q) && q > 1e-9 ? BuyCost[asset] / q : (double?)null;
|
||||
|
||||
/// <summary>被发行方冻结的数量(只有可冻结的币:CRT 在镇压期间、CRC),和解冻的日子。冻结的币仍计入余额与估值,但不能花、不能转。</summary>
|
||||
public Dictionary<string, double> Frozen = new Dictionary<string, double>();
|
||||
public Dictionary<string, int> FrozenUntil = new Dictionary<string, int>();
|
||||
|
||||
/// <summary>可动用的余额(扣掉冻结部分)。</summary>
|
||||
public double Avail(string asset) => Math.Max(0, Get(asset) - (Frozen.TryGetValue(asset, out var f) ? f : 0));
|
||||
|
||||
/// <summary>冻结该币当前余额的 share 比例,直到 untilDay(含)。已冻结的不重复冻。返回冻结的数量。</summary>
|
||||
public double Freeze(string asset, double share, int untilDay)
|
||||
{
|
||||
double amount = Avail(asset) * Math.Max(0, Math.Min(1, share));
|
||||
if (amount <= 1e-9) return 0;
|
||||
Frozen[asset] = (Frozen.TryGetValue(asset, out var f) ? f : 0) + amount;
|
||||
FrozenUntil[asset] = Math.Max(untilDay, FrozenUntil.TryGetValue(asset, out var u) ? u : 0);
|
||||
return amount;
|
||||
}
|
||||
|
||||
/// <summary>解冻到期的币,返回 (币种, 数量) 列表。</summary>
|
||||
public List<KeyValuePair<string, double>> Thaw(int day)
|
||||
{
|
||||
var list = new List<KeyValuePair<string, double>>();
|
||||
foreach (var a in new List<string>(FrozenUntil.Keys))
|
||||
if (day >= FrozenUntil[a])
|
||||
{
|
||||
list.Add(new KeyValuePair<string, double>(a, Frozen.TryGetValue(a, out var f) ? f : 0));
|
||||
Frozen.Remove(a); FrozenUntil.Remove(a);
|
||||
}
|
||||
return list;
|
||||
}
|
||||
|
||||
public double Get(string asset) => Balances.TryGetValue(asset, out var v) ? v : 0;
|
||||
|
||||
public void Add(string asset, double amount)
|
||||
{
|
||||
if (amount == 0) return;
|
||||
if (amount < 0 && BuyQty.TryGetValue(asset, out var bq))
|
||||
{
|
||||
double before = Get(asset), keep = before > 1e-12 ? Math.Max(0, 1 + amount / before) : 0;
|
||||
BuyQty[asset] = bq * keep; BuyCost[asset] *= keep;
|
||||
if (BuyQty[asset] < 1e-9) { BuyQty.Remove(asset); BuyCost.Remove(asset); }
|
||||
}
|
||||
double v = Get(asset) + amount;
|
||||
if (v < -1e-9) throw new InvalidOperationException($"{Address}: {asset} 余额不足");
|
||||
if (Math.Abs(v) < 1e-12) Balances.Remove(asset);
|
||||
@@ -31,10 +108,19 @@ namespace Decentralized.Domain
|
||||
}
|
||||
|
||||
/// <summary>按价格表估值(信用点)。</summary>
|
||||
/// <summary>花掉(销毁)一笔币:污点与成本按这笔币占钱包总价值的比例一起带走。</summary>
|
||||
public void Spend(string asset, double amount, Func<string, double> price)
|
||||
{
|
||||
double total = Value(price), share = total > 0 ? Math.Min(1, amount * price(asset) / total) : 0;
|
||||
double taint = Taint * share, basis = Basis * share;
|
||||
Add(asset, -amount); Taint -= taint; Basis -= basis;
|
||||
}
|
||||
|
||||
public double Value(Func<string, double> price) => Balances.Sum(kv => kv.Value * price(kv.Key));
|
||||
|
||||
/// <summary>
|
||||
/// 转出:taint 和 basis 按转出价值占地址总价值的比例带走。Ponero 等不可追踪资产转入时,污点不随之进入目标地址。
|
||||
/// 转出:taint 和 basis 按转出价值占地址总价值的比例带走;被标记的地址转出可追踪的币,收款地址也被标记。
|
||||
/// Ponero 等不可追踪资产转入时,污点和标记都不随之进入目标地址。
|
||||
/// </summary>
|
||||
public static void Transfer(Wallet from, Wallet to, string asset, double amount, Func<string, double> price)
|
||||
{
|
||||
@@ -47,7 +133,7 @@ namespace Decentralized.Domain
|
||||
from.Basis -= basis;
|
||||
to.Add(asset, amount);
|
||||
var spec = Assets.Get(asset);
|
||||
if (spec == null || spec.Traceable) to.Taint += taint;
|
||||
if (spec == null || spec.Traceable) { to.Taint += taint; if (from.Flagged) to.Flagged = true; }
|
||||
to.Basis += basis;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,162 @@
|
||||
using System;
|
||||
using System.Runtime.CompilerServices;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using Decentralized.Domain;
|
||||
using UnityEngine;
|
||||
|
||||
namespace Decentralized
|
||||
{
|
||||
/// <summary>
|
||||
/// RatDigg 矿机(M1 / M2 / M3):独立的机器,窗口里有电池槽、模块槽(和矿架同一套效果)和修理槽,没有显卡槽。
|
||||
/// 夜间和矿架一样先从电池扣电、有电才挖;损耗与暴毙沿用 <see cref="Unit"/>(暴毙系数 0.5,每天损耗 0.8)。
|
||||
/// 暴毙后成了"损坏的矿机":往修理槽里按顺序放电子元件修好(见 <see cref="AsicRepair"/>),健康扣 20 点。
|
||||
/// </summary>
|
||||
public static class AsicItems
|
||||
{
|
||||
public const string Prefix = "pd_asic_";
|
||||
public const string StepTag = "PD_REPAIR_STEP", ProgTag = "PD_REPAIR_PROG";
|
||||
|
||||
public static string Id(string model) => Prefix + model.ToLowerInvariant();
|
||||
public static bool Is(GameItem it) => it != null && it.identifier != null && it.identifier.StartsWith(Prefix);
|
||||
|
||||
public static void Register(ModItemDirectory dir)
|
||||
{
|
||||
foreach (var spec in Hardware.Specs.Values.Where(s => s.Asic))
|
||||
{
|
||||
var s = spec;
|
||||
dir.Add(Id(s.Model), () => Create(s));
|
||||
}
|
||||
}
|
||||
|
||||
private static int Step(GameItem m) => m.IsTag(StepTag) ? m.GetTagReadonly(StepTag).GetInt() : 0;
|
||||
private static int Prog(GameItem m) => m.IsTag(ProgTag) ? m.GetTagReadonly(ProgTag).GetInt() : 0;
|
||||
|
||||
private static readonly ConditionalWeakTable<GameItem, GameInventory> ModulesOf = new ConditionalWeakTable<GameItem, GameInventory>();
|
||||
|
||||
/// <summary>这件电子元件能不能修这台矿机:机器烧坏了,而且这一步要的就是这种元件。电子元件拖到机器上修,没有修理槽。</summary>
|
||||
public static bool CanRepairWith(GameItem m, GameItem src)
|
||||
{
|
||||
if (!Is(m) || src == null || !GeneralHelper.IsItemOwned(src) || !GeneralHelper.IsItemOwned(m)) return false;
|
||||
var u = Items.ToUnit(m);
|
||||
var need = AsicRepair.Need(u.Model, Step(m));
|
||||
return u.Dead && need != null && src.identifier == need.Value.Item;
|
||||
}
|
||||
|
||||
/// <summary>修理:每次收一件,攒够这一步再进下一步,全部攒够就修好。</summary>
|
||||
public static void TakeRepair(GameItem m, GameItem item)
|
||||
{
|
||||
if (!CanRepairWith(m, item) || !ModulesOf.TryGetValue(m, out var modules)) return;
|
||||
var u = Items.ToUnit(m);
|
||||
int step = Step(m), prog = Prog(m);
|
||||
int took = AsicRepair.Insert(u.Model, ref step, ref prog, item.identifier, 1);
|
||||
if (took <= 0) return;
|
||||
m.ModifyTag(StepTag, s => s.Enable().SetInt(step));
|
||||
m.ModifyTag(ProgTag, s => s.Enable().SetInt(prog));
|
||||
if (item.unitCount <= 1) item.Destroy(); else item.GetSplitItem(1).Destroy();
|
||||
if (AsicRepair.Done(u.Model, step))
|
||||
{
|
||||
u.Dead = false;
|
||||
u.Health = Math.Max(10, u.Health - Tuning.AsicRepairHealthCut);
|
||||
m.ModifyTag(Items.DeadTag, s => s.Disable());
|
||||
m.ModifyTag(StepTag, s => s.Enable().SetInt(0));
|
||||
m.ModifyTag(ProgTag, s => s.Enable().SetInt(0));
|
||||
Items.Store(m, u);
|
||||
Log.Info($"矿机 {u.Model} 修好了,健康 {u.Health:0}");
|
||||
}
|
||||
EmporiumAudioPlayer.Instance?.ratchet?.Play();
|
||||
Update(m, modules);
|
||||
}
|
||||
|
||||
private static GameItem Create(HardwareSpec spec)
|
||||
{
|
||||
var battery = new GameSlotInventory();
|
||||
var modules = new GameGridInventory(MachineHelper.DEFAULT_MODULE_BAY_CONFIG, 7);
|
||||
GameItem machine = null;
|
||||
var stHash = new MachineryText("", 6, TMPro.HorizontalAlignmentOptions.Left, false);
|
||||
var stPower = new MachineryText("", 6, TMPro.HorizontalAlignmentOptions.Left, false);
|
||||
var stCond = new MachineryText("", 6, TMPro.HorizontalAlignmentOptions.Left, false);
|
||||
var addr = new MachineryStack(true, 6).Add(stHash).Add(stPower).Add(stCond).Add(Payout.Build(() => machine, out var stAddr));
|
||||
var window = MachineHelper.CreateMachineryWindow(true,
|
||||
MachineHelper.PowerPanel(battery),
|
||||
MachineHelper.Panel(L.T("rig.label.modules"), modules, "module"),
|
||||
MachineHelper.Panel(L.T("rig.label.status"), addr, "status", false));
|
||||
var m = ItemDirectory.CreateEmptyItem(Id(spec.Model)).SetContentWindow(window);
|
||||
machine = m;
|
||||
Payout.Register(m, stAddr);
|
||||
RigStatus.Add(m, new[] { stHash, stPower, stCond });
|
||||
m.SetSpriteAndShapeFromMod(ModInfo.Id, "asic_" + spec.Model.ToLowerInvariant());
|
||||
m.name = L.T("item.asic.name", spec.Model);
|
||||
m.unitValue = spec.Price;
|
||||
MachineHelper.SetupBatterySlot(battery, m);
|
||||
m.EnableTag("CONTAINER_TAG");
|
||||
m.EnableTag("STANDARD_MACHINE_TAG");
|
||||
MachineryHelper.InitMachinery(m, (int)Math.Ceiling(spec.Kj));
|
||||
MachineHelper.SetupModuleBay(modules, m, () => Update(m, modules));
|
||||
ModulesOf.Remove(m); ModulesOf.Add(m, modules);
|
||||
m.onLoaded = _ => Update(m, modules);
|
||||
m.onCycleEndEarlySlotItemFunc = (_, _, _) => Log.Guard("矿机扣电", () => NightDraw(m, battery, modules));
|
||||
ModHelper.SetSource(m, ModInfo.Id, ModInfo.Name);
|
||||
Update(m, modules);
|
||||
return m;
|
||||
}
|
||||
|
||||
/// <summary>名字、说明、价值与耗电(耗电按模块效果重算)。</summary>
|
||||
private static void Update(GameItem m, GameInventory modules)
|
||||
{
|
||||
var u = Items.ToUnit(m);
|
||||
var b = Items.Bonus(m, modules);
|
||||
int baseKj = (int)Math.Ceiling(u.Label.Kj);
|
||||
m.ModifyTag("MACHINERY_DRAWN_POWER_BASE", s => s.Enable().SetInt(baseKj));
|
||||
m.ModifyTag(MachineryHelper.MACHINERY_DRAWN_POWER, s => s.Enable().SetInt(u.Dead ? 0 : (int)Math.Ceiling(u.Kj(b))));
|
||||
RigStatus.ShowAsic(m, u.Dead ? 0 : u.Hash(b) * 10 / 1000, u.Dead ? 0 : (int)Math.Ceiling(u.Kj(b)), u.Health, u.Dead);
|
||||
Payout.Refresh(m);
|
||||
Describe(m, u);
|
||||
}
|
||||
|
||||
/// <summary>按标签刷新名字、说明、价值(夜间损耗之后也走这里)。</summary>
|
||||
public static void Refresh(GameItem m) => Describe(m, Items.ToUnit(m));
|
||||
|
||||
private static void Describe(GameItem m, Unit u)
|
||||
{
|
||||
var spec = u.Label;
|
||||
m.name = L.T(u.Dead ? "item.asic.dead.name" : "item.asic.name", spec.Model);
|
||||
if (u.Dead)
|
||||
{
|
||||
var need = AsicRepair.Need(u.Model, Step(m));
|
||||
m.shortDescription = need == null ? L.T("item.asic.dead.fixed") : L.T("item.asic.dead.desc", L.T("mat." + need.Value.Item), need.Value.Count - Prog(m));
|
||||
m.unitValue = Math.Max(1, (long)Math.Round(spec.Price * Tuning.AsicDeadValue));
|
||||
return;
|
||||
}
|
||||
string cond = GeneralHelper.IsItemOwned(m)
|
||||
? Mathf.RoundToInt((float)u.Health) + "%"
|
||||
: L.T(u.Health >= 85 ? "item.gpu.grade.1" : u.Health >= 60 ? "item.gpu.grade.2" : u.Health >= 35 ? "item.gpu.grade.3" : "item.gpu.grade.4");
|
||||
m.shortDescription = L.T("item.asic.desc", Fmt.Num(spec.DisplayHash), Fmt.Num(spec.Kj), cond);
|
||||
m.unitValue = CardValue.Of(spec.Model, u.Health);
|
||||
}
|
||||
|
||||
private static void NightDraw(GameItem m, GameSlotInventory battery, GameInventory modules)
|
||||
{
|
||||
if (!Session.TonightDrawn.Add(m.uniqueId)) return;
|
||||
var u = Items.ToUnit(m);
|
||||
Session.TonightRigs++;
|
||||
if (u.Dead) return;
|
||||
var b = Items.Bonus(m, modules);
|
||||
int kj = (int)Math.Ceiling(u.Kj(b));
|
||||
if (battery.childItems.Count == 0 || !PowerHelper.DrawPowerSource(battery.childItem, kj)) return;
|
||||
Session.TonightPoweredRigs++;
|
||||
Session.TonightKj += kj;
|
||||
Session.TonightCards.Add(new KeyValuePair<GameItem, ModuleBonus>(m, b));
|
||||
Session.TonightMachine[m] = m;
|
||||
Update(m, modules);
|
||||
}
|
||||
|
||||
/// <summary>造一台矿机:按健康度写标签。</summary>
|
||||
public static GameItem New(string model, double health)
|
||||
{
|
||||
var item = ModHelper.SpawnItem(Id(model));
|
||||
Items.Store(item, new Unit { Model = model, Health = health });
|
||||
return item;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,223 @@
|
||||
using System;
|
||||
using System.Linq;
|
||||
using Decentralized.Domain;
|
||||
|
||||
namespace Decentralized
|
||||
{
|
||||
/// <summary>
|
||||
/// Web3 黑市的货物进出:每周刷新现货与订单目录,夜间推进订单并写夜间日志,
|
||||
/// 上门(快递员当顾客上门)把到货交给玩家。
|
||||
/// </summary>
|
||||
public static class BlackDelivery
|
||||
{
|
||||
public static void Subscribe()
|
||||
{
|
||||
ModHook.OnGenerateCustomerNormal += OnGenerate;
|
||||
}
|
||||
|
||||
public static void Unsubscribe()
|
||||
{
|
||||
ModHook.OnGenerateCustomerNormal -= OnGenerate;
|
||||
}
|
||||
|
||||
private static readonly System.Collections.Generic.Dictionary<string, long> ValueCache = new System.Collections.Generic.Dictionary<string, long>();
|
||||
|
||||
public static long Value(string id)
|
||||
{
|
||||
if (ValueCache.TryGetValue(id, out var cached)) return cached;
|
||||
var it = ModHelper.SpawnItem(id);
|
||||
long v = 0;
|
||||
if (it != null) { v = it.GetBaseValue(); it.Destroy(); }
|
||||
ValueCache[id] = v;
|
||||
return v;
|
||||
}
|
||||
|
||||
/// <summary>货架上的货对应的游戏物品 id:显卡是 "gpu:型号",对应本 mod 的显卡物品。</summary>
|
||||
public static string GameId(string id) => id.StartsWith("gpu:") ? (Hardware.Specs.TryGetValue(id.Substring(4), out var sp) && sp.Asic ? AsicItems.Id(sp.Model) : Items.GpuId(id.Substring(4))) : id;
|
||||
|
||||
/// <summary>造出这件货:显卡按成色与(可能的)假卡真身造,不带卖家的说法;其余直接造。</summary>
|
||||
public static GameItem Make(string id, string model, string fakeOf, double health)
|
||||
{
|
||||
if (id.StartsWith("gpu:")) return Hardware.Specs[model].Asic ? AsicItems.New(model, health) : Items.NewCard(model, health, fakeOf, Session.Data.Rng);
|
||||
if (id == Items.HwWallet) return Items.NewHwWallet(Session.Data.Rng.Chance(Scales.R(Tuning.WalletPoisonShare)));
|
||||
return ModHelper.SpawnItem(id);
|
||||
}
|
||||
|
||||
/// <summary>商家名:随机的匿名哈希,类型另外标注。</summary>
|
||||
public static string DisplayName(string name) => name;
|
||||
|
||||
public static string ItemName(string id)
|
||||
{
|
||||
var it = ModHelper.SpawnItem(GameId(id));
|
||||
if (it == null) return id;
|
||||
string n = it.name;
|
||||
it.Destroy();
|
||||
return n;
|
||||
}
|
||||
|
||||
// ---- 玩家出售:从储藏区挑能上架的货 ----
|
||||
|
||||
/// <summary>这件物品在黑市上的货 id(显卡是 "gpu:型号",其余是物品 id);不能上架返回 null。</summary>
|
||||
public static string SellId(GameItem it)
|
||||
{
|
||||
if (it == null || it.identifier == null) return null;
|
||||
if (Items.IsGpu(it) || AsicItems.Is(it)) return "gpu:" + Items.ToUnit(it).Model;
|
||||
string id = it.identifier;
|
||||
return Merchants.IsGood(id) ? id : null;
|
||||
}
|
||||
|
||||
/// <summary>自己的储藏区、背包不能上架:卖掉会带走里面的东西,也会丢掉容量。</summary>
|
||||
private static readonly System.Collections.Generic.HashSet<string> StorageIds = new System.Collections.Generic.HashSet<string>(Merchants.Table[MerchantType.Storage].Select(e => e.Id));
|
||||
|
||||
public static System.Collections.Generic.List<GameItem> Sellable() =>
|
||||
GraphUtils.FindAllChildrenType<GameItem>(EmporiumEntry.Instance.invElement, i => GeneralHelper.IsItemOwned(i) && SellId(i) != null && !i.IsTag(Items.DeadTag) && !StorageIds.Contains(i.identifier) && i.FindAllChildItems().Count == 0, i => i.identifier != Items.Rig);
|
||||
|
||||
/// <summary>参考价:显卡按标称型号与成色,其余按游戏基础价。</summary>
|
||||
public static long RefValue(GameItem it)
|
||||
{
|
||||
string id = SellId(it);
|
||||
if (id == null) return 0;
|
||||
if (Items.IsGpu(it) || AsicItems.Is(it)) { var u = Items.ToUnit(it); return CardValue.Of(u.Model, u.Health); }
|
||||
return Value(id);
|
||||
}
|
||||
|
||||
public static GoodKind KindOf(string id) => id.StartsWith("gpu:") ? GoodKind.Gpu : Merchants.Info(id).Kind;
|
||||
|
||||
/// <summary>每周刷新:现货与订单目录一起。返回是否刷新了。</summary>
|
||||
public static bool Restock(SaveData d, int day, bool force = false)
|
||||
{
|
||||
int rep = StoreReputation.GetBMReputation();
|
||||
if (d.Black.Closed(day)) return false;
|
||||
if (force) d.Black.RefreshedDay = -999;
|
||||
if (!d.Black.Refresh(day, rep, d.Rng, Value)) return false;
|
||||
d.Black.RefreshOrders(day, rep, d.Rng, Value);
|
||||
// 平台现货偶尔有硬件钱包:比杰克逊博士便宜,外观一样,其中一部分被动过手脚
|
||||
if (d.Rng.Chance(Tuning.WalletMallChance))
|
||||
d.Black.Offers.Add(new BmOffer { Item = Items.HwWallet, Kind = GoodKind.Tech, Price = d.Rng.Range(Tuning.WalletMallMin, Tuning.WalletMallMax), Qty = d.Rng.Range(1, Tuning.WalletMallQtyMax) });
|
||||
Log.Info($"黑市刷新(第 {day} 天):现货 {d.Black.Offers.Count} 种,商家 {d.Black.Sellers.Count} 家({string.Join("/", d.Black.Sellers.Select(x => x.Type))}),货架 {d.Black.Catalog.Count} 种共 {d.Black.CatalogValue:0} 信用点,高科技 {d.Black.Offers.Count(o => o.Kind == GoodKind.Tech)},显卡 {d.Black.Offers.Count(o => o.Kind == GoodKind.Gpu)}");
|
||||
return true;
|
||||
}
|
||||
|
||||
public static void Night(SaveData d, int day, bool crackdown)
|
||||
{
|
||||
var ps = PlayerStore.Instance;
|
||||
foreach (var e in d.Black.Night(day, crackdown, d.WalletAt, d.Rng, StoreReputation.GetSecReputation(), Session.Price))
|
||||
{
|
||||
if (e.Sale != null)
|
||||
{
|
||||
string sname = ItemName(e.Sale.Item);
|
||||
Log.Info($"黑市出售事件:{e.Kind} {e.Sale.Item} ×{e.Sale.Mult} 货款 {e.Amount:0} 污点 {e.Sale.Taint:0}");
|
||||
switch (e.Kind)
|
||||
{
|
||||
case "sale_sold": ps.AddNightLog(L.T("nightlog.bm.sale_sold", sname, Fmt.Num(e.Amount), e.Sale.PayDay), "99bb66"); break;
|
||||
case "sale_paid": ps.AddNightLog(L.T("nightlog.bm.sale_paid", sname, Fmt.Num(e.Amount), Fmt.Num(e.Sale.Taint)), "99bb66"); break;
|
||||
case "sale_fake":
|
||||
Items.Give(Make(e.Sale.Item, e.Sale.Model, e.Sale.FakeOf, e.Sale.Health));
|
||||
ps.AddNightLog(L.T("nightlog.bm.sale_fake", sname), "cc7755");
|
||||
break;
|
||||
case "sale_rug": ps.AddNightLog(L.T("nightlog.bm.sale_rug", sname, Fmt.Num(e.Amount)), "cc7755"); break;
|
||||
}
|
||||
if (e.Kind == "sale_rug") News.Show("pd_news_bmrug_" + day, L.T("news.bmrug.title"), L.T("news.bmrug.desc"), 4);
|
||||
continue;
|
||||
}
|
||||
string name = e.Order != null && e.Kind != "trap" ? ItemName(e.Order.Item) : null;
|
||||
Log.Info($"黑市订单事件:{e.Kind} {e.Order?.Item} {e.Order?.Seller} {e.Order?.Mode} 受控 {e.Order?.Controlled} 金额 {e.Amount:0}");
|
||||
switch (e.Kind)
|
||||
{
|
||||
case "ready": ps.AddNightLog(L.T("nightlog.bm.ready", name), "99bb66"); break;
|
||||
case "scam_refund": ps.AddNightLog(L.T("nightlog.bm.scam_refund", DisplayName(e.Order.Seller), name), "cc7755"); break;
|
||||
case "scam_loss": ps.AddNightLog(L.T("nightlog.bm.scam_loss", DisplayName(e.Order.Seller), name, Fmt.Num(e.Amount)), "cc7755"); break;
|
||||
case "intercept": ps.AddNightLog(L.T("nightlog.bm.intercept", name, Fmt.Num(e.Amount)), "cc7755"); break;
|
||||
case "rug": ps.AddNightLog(L.T("nightlog.bm.rug", name, Fmt.Num(e.Amount)), "cc7755"); break;
|
||||
case "trap":
|
||||
{
|
||||
int amount = (int)Math.Min(Tuning.CrimeEventCap, e.Amount);
|
||||
ps.secData.CommitCrime(e.Order.Item != null && e.Order.Item.StartsWith("gpu:") ? "FENCING" : "CONTRABAND_TRAFFICKING", amount);
|
||||
Log.Info($"黑市追查:记罪证 {amount}({e.Order.Seller})");
|
||||
ps.AddNightLog(L.T("nightlog.bm.trap." + e.Order.Seller, ItemName(e.Order.Item), amount), "cc7755");
|
||||
break;
|
||||
}
|
||||
case "reopen": ps.AddNightLog(L.T("nightlog.bm.reopen"), "99bb66"); break;
|
||||
}
|
||||
if (e.Kind == "rug") Night_RugNews(day);
|
||||
}
|
||||
if (Unlock.BlackUnlocked && !crackdown) Restock(d, day);
|
||||
}
|
||||
|
||||
private static void Night_RugNews(int day) => News.Show("pd_news_bmrug_" + day, L.T("news.bmrug.title"), L.T("news.bmrug.desc"), 4);
|
||||
|
||||
// ---- 上门:开门后有到货的当天,快递员排进顾客队伍 ----
|
||||
private static int courierDay = -1;
|
||||
|
||||
private static void OnGenerate(StoreClientManager manager)
|
||||
{
|
||||
if (Session.Data == null || !Unlock.BlackUnlocked) return;
|
||||
Log.Guard("黑市快递员", () =>
|
||||
{
|
||||
int day = StoreStation.GetDayCounter();
|
||||
if (day == courierDay || !Session.Data.Black.Ready.Any()) return;
|
||||
courierDay = day;
|
||||
manager.AddClient(CreateCourier());
|
||||
});
|
||||
}
|
||||
|
||||
public static StoreClient CreateCourier()
|
||||
{
|
||||
var rng = Session.Data.Rng;
|
||||
var c = new StoreClient
|
||||
{
|
||||
identifier = "pd_bm_courier",
|
||||
displayName = L.T("courier.name"),
|
||||
spriteName = SpriteDict.GetRandomScavSpriteName(),
|
||||
clientIntent = StoreClient.ClientIntent.SELL,
|
||||
};
|
||||
StoreClientFactionSetup.InitScav(c);
|
||||
var trap = Session.Data.Black.Ready.FirstOrDefault(o => o.Controlled);
|
||||
Action finish = () => { PlayerStore.Instance.DismissCurrentClient(); };
|
||||
if (trap == null)
|
||||
{
|
||||
c.mainDialogue.SetText(c.displayName, L.T("courier.line1." + rng.Range(1, 2))).NextDialogue().SetText(c.displayName, L.T("courier.line2." + rng.Range(1, 2)))
|
||||
.SetEndAction(() => Log.Guard("黑市快递交货", () => { DeliverDoor(); finish(); }));
|
||||
}
|
||||
else
|
||||
{
|
||||
// 受控交付:快递员神色异常,签收就是当场记罪证并查封,拒签只损失货款
|
||||
var sign = new Dialogue();
|
||||
sign.SetText("PLAYER", L.T("courier.sign.say"));
|
||||
sign.NextDialogue().SetText(c.displayName, L.T("courier.signed")).SetEndAction(() => Log.Guard("受控交付签收", () =>
|
||||
{
|
||||
int amount = (int)Math.Min(Tuning.CrimeEventCap, Session.Data.Black.Sign(trap, true));
|
||||
PlayerStore.Instance.secData.CommitCrime(trap.Item.StartsWith("gpu:") ? "FENCING" : "CONTRABAND_TRAFFICKING", amount);
|
||||
Log.Info($"受控交付:签收,记罪证 {amount},货被查封");
|
||||
DeliverDoor(); finish();
|
||||
}));
|
||||
var refuse = new Dialogue();
|
||||
refuse.SetText("PLAYER", L.T("courier.refuse.say"));
|
||||
refuse.NextDialogue().SetText(c.displayName, L.T("courier.refused")).SetEndAction(() => Log.Guard("受控交付拒签", () => { Session.Data.Black.Sign(trap, false); Log.Info("受控交付:拒签"); DeliverDoor(); finish(); }));
|
||||
c.mainDialogue.SetText(c.displayName, L.T("courier.odd1")).NextDialogue().SetText(c.displayName, L.T("courier.odd2"))
|
||||
.AddChoice(DirectoryMaster.Item("yes"), L.T("courier.sign"), "", sign, null)
|
||||
.AddChoice(DirectoryMaster.Item("cancel"), L.T("courier.refuse"), "", refuse, null);
|
||||
}
|
||||
c.AddBasicDialog();
|
||||
c.CompleteClientCreation();
|
||||
return c;
|
||||
}
|
||||
|
||||
private static void DeliverDoor()
|
||||
{
|
||||
var d = Session.Data;
|
||||
foreach (var o in d.Black.Ready.Where(x => !x.Controlled).ToList())
|
||||
{
|
||||
for (int i = 0; i < o.Count; i++)
|
||||
{
|
||||
var made = Make(o.Item, o.Model, o.FakeOf, o.Health);
|
||||
Items.Give(made);
|
||||
if (o.Item.StartsWith("gpu:")) { var u = Items.ToUnit(made); Log.Info($"黑市到货显卡:标称 {u.Model} 真身 {(u.FakeOf ?? "(真卡)")} 成色 {u.Health:0} 外观 {u.Look.Encode()}"); }
|
||||
}
|
||||
d.Black.Deliver(o);
|
||||
Log.Info($"黑市快递:{o.Item} ×{o.Count}{(o.FakeOf != null ? "(假卡,真身 " + o.FakeOf + ")" : "")} 已放进储藏区");
|
||||
}
|
||||
Session.Save();
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,249 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Globalization;
|
||||
using System.Linq;
|
||||
using Decentralized.Domain;
|
||||
using UnityEngine;
|
||||
|
||||
namespace Decentralized
|
||||
{
|
||||
/// <summary>
|
||||
/// 日 K 图:运行时画到一张小 Texture2D 上(一根蜡烛 5 像素宽、间隔 1),点采样放大 2 倍显示,和游戏的像素风格一致。
|
||||
/// 上面是价格(涨绿跌红、影线、7 日均线、可选阈值虚线),下面是成交量(玩家青色叠在大户灰色上)。纹理按用途缓存复用。
|
||||
/// </summary>
|
||||
public static class CandleChart
|
||||
{
|
||||
/// <summary>画图的币种:全部可交易资产。</summary>
|
||||
public static readonly string[] ChartAssets = { Assets.PSC, Assets.SPARK, Assets.CRT, Assets.CRA, Assets.CRC, Assets.Ponero };
|
||||
|
||||
private static double VolShare(string a) =>
|
||||
a == Assets.PSC ? Tuning.ChartVolPsc : a == Assets.CRC ? Tuning.ChartVolCrc : a == Assets.CRT ? Tuning.ChartVolCrt :
|
||||
a == Assets.CRA ? Tuning.ChartVolCra : a == Assets.SPARK ? Tuning.ChartVolSpark : Tuning.ChartVolPonero;
|
||||
|
||||
/// <summary>开门:每个币开一根蜡烛(开盘接昨天收盘,夜里的价格变化算进来)。</summary>
|
||||
public static void Morning(SaveData d, int day)
|
||||
{
|
||||
foreach (var a in ChartAssets) d.Candles.Open(a, day, Session.Price(a));
|
||||
}
|
||||
|
||||
/// <summary>白天价格变了(不计成交)。</summary>
|
||||
public static void Touch(SaveData d, int day, params string[] assets)
|
||||
{
|
||||
foreach (var a in assets) d.Candles.Tick(a, day, Session.Price(a));
|
||||
}
|
||||
|
||||
/// <summary>玩家的一笔成交:按信用点计进这个币当天的成交量。</summary>
|
||||
public static void Trade(string asset, double credits)
|
||||
{
|
||||
var d = Session.Data;
|
||||
if (d == null || Array.IndexOf(ChartAssets, asset) < 0 || credits <= 0) return;
|
||||
d.Candles.Tick(asset, StoreStation.GetDayCounter(), Session.Price(asset), credits, true);
|
||||
}
|
||||
|
||||
/// <summary>夜间结算:补上当天 NPC 的成交量,收盘。在价格的夜间更新之前调用。</summary>
|
||||
public static void Close(SaveData d, int day)
|
||||
{
|
||||
double depth = Tuning.PoolDepth(day);
|
||||
foreach (var a in ChartAssets)
|
||||
{
|
||||
double p = Session.Price(a);
|
||||
var c = d.Candles.Today(a, day, p);
|
||||
double move = c.O > 0 ? Math.Abs(p / c.O - 1) + (c.H - c.L) / c.O : 0;
|
||||
d.Candles.Tick(a, day, p, CandleBook.NpcVolume(depth, VolShare(a), move, d.Rng));
|
||||
d.Candles.Close(a, day, p);
|
||||
}
|
||||
}
|
||||
|
||||
private static readonly Dictionary<string, string> Picked = new Dictionary<string, string>();
|
||||
|
||||
public const int Days = 30, Step = 6, Body = 5, PriceH = 70, Gap = 3, VolH = 16, Pad = 2, AxisW = 22, DateH = 7;
|
||||
public const int W = Days * Step + Pad * 2 + AxisW, H = PriceH + Gap + VolH + Pad * 2 + DateH;
|
||||
public static float Scale => TerminalWindow.ChartScale;
|
||||
|
||||
private static readonly Color32 Bg = new Color32(30, 31, 34, 255), Grid = new Color32(48, 50, 54, 255);
|
||||
private static readonly Color32 Up = new Color32(108, 190, 112, 255), Down = new Color32(214, 94, 88, 255);
|
||||
private static readonly Color32 Ma = new Color32(226, 196, 92, 255), Thr = new Color32(150, 170, 230, 255);
|
||||
private static readonly Color32 VolNpc = new Color32(92, 96, 104, 255), VolMe = new Color32(96, 200, 210, 255);
|
||||
private static readonly Color32 Txt = new Color32(150, 154, 160, 255), TagBg = new Color32(226, 196, 92, 255), TagTxt = new Color32(30, 31, 34, 255);
|
||||
|
||||
/// <summary>3×5 像素数字字体(每行 3 位,自上而下)。</summary>
|
||||
private static readonly Dictionary<char, string[]> Glyph = new Dictionary<char, string[]>
|
||||
{
|
||||
['0'] = new[] { "111", "101", "101", "101", "111" }, ['1'] = new[] { "010", "110", "010", "010", "111" },
|
||||
['2'] = new[] { "111", "001", "111", "100", "111" }, ['3'] = new[] { "111", "001", "011", "001", "111" },
|
||||
['4'] = new[] { "101", "101", "111", "001", "001" }, ['5'] = new[] { "111", "100", "111", "001", "111" },
|
||||
['6'] = new[] { "111", "100", "111", "101", "111" }, ['7'] = new[] { "111", "001", "010", "010", "010" },
|
||||
['8'] = new[] { "111", "101", "111", "101", "111" }, ['9'] = new[] { "111", "101", "111", "001", "111" },
|
||||
['.'] = new[] { "0", "0", "0", "0", "1" }, ['-'] = new[] { "000", "000", "111", "000", "000" },
|
||||
['k'] = new[] { "100", "101", "110", "101", "101" },
|
||||
};
|
||||
|
||||
private static int TextW(string s) => s.Sum(ch => Glyph.TryGetValue(ch, out var g) ? g[0].Length + 1 : 0) - 1;
|
||||
|
||||
/// <summary>在 (x, y) 处写字,y 是字的底边。</summary>
|
||||
private static void Text(Color32[] px, int x, int y, string s, Color32 c)
|
||||
{
|
||||
foreach (char ch in s)
|
||||
{
|
||||
if (!Glyph.TryGetValue(ch, out var g)) continue;
|
||||
for (int r = 0; r < 5; r++)
|
||||
for (int k = 0; k < g[r].Length; k++)
|
||||
if (g[r][k] == '1') Set(px, x + k, y + 4 - r, c);
|
||||
x += g[0].Length + 1;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>刻度上的价格:大于 100 不带小数,越小小数越多,最多 5 个字符左右。</summary>
|
||||
private static string Num(double p)
|
||||
{
|
||||
if (p >= 10000) return (p / 1000).ToString("0", CultureInfo.InvariantCulture) + "k";
|
||||
if (p >= 100) return p.ToString("0", CultureInfo.InvariantCulture);
|
||||
if (p >= 10) return p.ToString("0.0", CultureInfo.InvariantCulture);
|
||||
if (p >= 1) return p.ToString("0.00", CultureInfo.InvariantCulture);
|
||||
return p.ToString("0.000", CultureInfo.InvariantCulture).Substring(1);
|
||||
}
|
||||
|
||||
private sealed class Slot { public Texture2D Tex; public Sprite Sprite; public Color32[] Px; }
|
||||
private static readonly Dictionary<string, Slot> Slots = new Dictionary<string, Slot>();
|
||||
|
||||
/// <summary>画一张图,返回可以交给 AddImage 的 Sprite。threshold > 0 时画一条水平虚线(预测盘的阈值)。</summary>
|
||||
public static Sprite Render(string key, IList<Candle> all, double threshold = 0)
|
||||
{
|
||||
if (!Slots.TryGetValue(key, out var s) || s.Tex == null)
|
||||
{
|
||||
var tex = new Texture2D(W, H, TextureFormat.RGBA32, false) { filterMode = FilterMode.Point, wrapMode = TextureWrapMode.Clamp };
|
||||
s = Slots[key] = new Slot { Tex = tex, Px = new Color32[W * H], Sprite = Sprite.Create(tex, new Rect(0, 0, W, H), new Vector2(0.5f, 0.5f), 100f) };
|
||||
}
|
||||
var px = s.Px;
|
||||
for (int i = 0; i < px.Length; i++) px[i] = Bg;
|
||||
var c = all.Skip(Math.Max(0, all.Count - Days)).ToList();
|
||||
int volY0 = Pad + DateH, priceY0 = volY0 + VolH + Gap, plotR = Pad + Days * Step, axisX = plotR + 2;
|
||||
// 网格:价格区四等分
|
||||
for (int g = 1; g < 4; g++) HLine(px, Pad, plotR - 1, priceY0 + PriceH * g / 4, Grid);
|
||||
VLine(px, plotR, volY0, priceY0 + PriceH - 1, Grid);
|
||||
if (c.Count > 0)
|
||||
{
|
||||
var ma = CandleBook.Ma(all, 7).Skip(Math.Max(0, all.Count - Days)).ToList();
|
||||
double lo = Math.Min(c.Min(x => x.L), ma.Min()), hi = Math.Max(c.Max(x => x.H), ma.Max());
|
||||
if (threshold > 0) { lo = Math.Min(lo, threshold); hi = Math.Max(hi, threshold); }
|
||||
double span = Math.Max(hi - lo, hi * 0.02);
|
||||
lo -= span * 0.05; hi += span * 0.05; span = hi - lo;
|
||||
Func<double, int> y = p => priceY0 + (int)Math.Round((p - lo) / span * (PriceH - 1));
|
||||
double vmax = Math.Max(1, c.Max(x => x.VolPlayer + x.VolNpc));
|
||||
int x0 = Pad + (Days - c.Count) * Step; // 不足 30 根时靠右
|
||||
// 均线先画,蜡烛盖在上面(贴着锚的稳定币不会被均线遮住)
|
||||
for (int i = 1; i < ma.Count; i++) Line(px, x0 + (i - 1) * Step + Body / 2, y(ma[i - 1]), x0 + i * Step + Body / 2, y(ma[i]), Ma);
|
||||
for (int i = 0; i < c.Count; i++)
|
||||
{
|
||||
var k = c[i];
|
||||
int left = x0 + i * Step, mid = left + Body / 2;
|
||||
var col = k.C >= k.O ? Up : Down;
|
||||
VLine(px, mid, y(k.L), y(k.H), col);
|
||||
int b0 = y(Math.Min(k.O, k.C)), b1 = Math.Max(b0, y(Math.Max(k.O, k.C)));
|
||||
for (int xx = left; xx < left + Body; xx++)
|
||||
{
|
||||
// 当天还没收盘的蜡烛画成空心
|
||||
if (!k.Closed && xx > left && xx < left + Body - 1 && b1 - b0 > 1) { Set(px, xx, b0, col); Set(px, xx, b1, col); continue; }
|
||||
VLine(px, xx, b0, b1, col);
|
||||
}
|
||||
int hn = (int)Math.Round(k.VolNpc / vmax * VolH), hm = (int)Math.Round(k.VolPlayer / vmax * VolH);
|
||||
for (int xx = left; xx < left + Body; xx++)
|
||||
{
|
||||
if (hn > 0) VLine(px, xx, volY0, volY0 + hn - 1, VolNpc);
|
||||
if (hm > 0) VLine(px, xx, volY0 + hn, volY0 + hn + hm - 1, VolMe);
|
||||
}
|
||||
}
|
||||
if (threshold > 0) { int ty = y(threshold); for (int xx = Pad; xx < plotR; xx++) if ((xx / 3) % 2 == 0) Set(px, xx, ty, Thr); }
|
||||
// 右侧刻度:三条网格线的价格;最新收盘价标成黄底的价签,和网格刻度挤在一起时让开
|
||||
int lastY = y(c[c.Count - 1].C);
|
||||
for (int g = 1; g < 4; g++)
|
||||
{
|
||||
int gy = priceY0 + PriceH * g / 4;
|
||||
if (Math.Abs(gy - lastY) < 7) continue;
|
||||
double gp = lo + (gy - priceY0) / (double)(PriceH - 1) * span;
|
||||
Text(px, axisX, gy - 2, Num(gp), Txt);
|
||||
}
|
||||
if (threshold > 0) { int ty = y(threshold); if (Math.Abs(ty - lastY) >= 7) Text(px, axisX, ty - 2, Num(threshold), Thr); }
|
||||
string tag = Num(c[c.Count - 1].C);
|
||||
int ty0 = Math.Max(priceY0, Math.Min(priceY0 + PriceH - 7, lastY - 3));
|
||||
for (int yy = ty0; yy < ty0 + 7; yy++) HLine(px, axisX - 1, Math.Min(W - 1, axisX + TextW(tag)), yy, TagBg);
|
||||
Text(px, axisX, ty0 + 1, tag, TagTxt);
|
||||
// 底部日期:天数是 5 的倍数的蜡烛下面写天数
|
||||
for (int i = 0; i < c.Count; i++)
|
||||
{
|
||||
if (c[i].Day % 5 != 0) continue;
|
||||
string ds = c[i].Day.ToString(CultureInfo.InvariantCulture);
|
||||
int cx = x0 + i * Step + Body / 2;
|
||||
VLine(px, cx, volY0 - 1, volY0 - 1, Txt);
|
||||
Text(px, Math.Max(0, Math.Min(plotR - TextW(ds), cx - TextW(ds) / 2)), Pad - 1, ds, Txt);
|
||||
}
|
||||
// 成交量区右上:这一屏最大的量
|
||||
Text(px, axisX, volY0 + VolH - 5, Num(vmax), VolNpc);
|
||||
}
|
||||
s.Tex.SetPixels32(px);
|
||||
s.Tex.Apply(false);
|
||||
return s.Sprite;
|
||||
}
|
||||
|
||||
/// <summary>图上方的一行说明:最高、最低、最新收盘,涨跌。</summary>
|
||||
public static string Caption(string asset, IList<Candle> all)
|
||||
{
|
||||
var c = all.Skip(Math.Max(0, all.Count - Days)).ToList();
|
||||
if (c.Count == 0) return L.T("chart.empty", asset);
|
||||
var last = c[c.Count - 1];
|
||||
double prev = c.Count > 1 ? c[c.Count - 2].C : last.O, chg = prev > 0 ? last.C / prev - 1 : 0;
|
||||
return L.T("chart.caption", asset, c.Count, Fmt.Num(c.Max(x => x.H)), Fmt.Num(c.Min(x => x.L)), Fmt.Num(last.C), (chg * 100).ToString("+0.0;-0.0;0.0", CultureInfo.InvariantCulture));
|
||||
}
|
||||
|
||||
private static void Set(Color32[] px, int x, int y, Color32 c) { if (x >= 0 && x < W && y >= 0 && y < H) px[y * W + x] = c; }
|
||||
private static void HLine(Color32[] px, int x0, int x1, int y, Color32 c) { for (int x = x0; x <= x1; x++) Set(px, x, y, c); }
|
||||
private static void VLine(Color32[] px, int x, int y0, int y1, Color32 c) { if (y1 < y0) (y0, y1) = (y1, y0); for (int y = y0; y <= y1; y++) Set(px, x, y, c); }
|
||||
|
||||
private static void Line(Color32[] px, int x0, int y0, int x1, int y1, Color32 c)
|
||||
{
|
||||
int dx = Math.Abs(x1 - x0), dy = -Math.Abs(y1 - y0), sx = x0 < x1 ? 1 : -1, sy = y0 < y1 ? 1 : -1, err = dx + dy;
|
||||
while (true)
|
||||
{
|
||||
Set(px, x0, y0, c);
|
||||
if (x0 == x1 && y0 == y1) break;
|
||||
int e2 = 2 * err;
|
||||
if (e2 >= dy) { err += dy; x0 += sx; }
|
||||
if (e2 <= dx) { err += dx; y0 += sy; }
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>把一个币的图放进界面:说明一行、黑框包裹的图、图例一行。</summary>
|
||||
public static void Add(CustomUIBuilder b, string key, string asset, double threshold = 0)
|
||||
{
|
||||
var all = Session.Data.Candles.Of(asset);
|
||||
b.AddLabel(Caption(asset, all), "chart_caption_dim");
|
||||
b.BeginPanel(W * Scale + 4f, H * Scale + 4f, TextAnchor.MiddleCenter, 2f, 0f, "chart_bezel");
|
||||
PledgerSkin.Slice(b.Last.image, "ui_hw_bezel", 5);
|
||||
b.AddImage(Render(key, all, threshold), W * Scale, H * Scale);
|
||||
b.End();
|
||||
b.AddLabel(L.T(threshold > 0 ? "chart.legend.thr" : "chart.legend"), "chart_legend_dim");
|
||||
}
|
||||
|
||||
/// <summary>某张图当前选中的币(没选过或不在列表里时是 fallback)。</summary>
|
||||
public static string Selected(string key, string fallback, IList<string> assets = null)
|
||||
{
|
||||
var list = assets ?? ChartAssets.Where(a => a != Assets.Ponero || Unlock.BlackUnlocked).ToList();
|
||||
return Picked.TryGetValue(key, out var cur) && list.Contains(cur) ? cur : fallback;
|
||||
}
|
||||
|
||||
/// <summary>带币种切换的图:上面一排币种按钮(选中项带准星角标),切换后重画。assets 为空时是全部币种。</summary>
|
||||
public static void AddPicker(CustomUIBuilder b, string key, string fallback, Action refresh, ICollection<GameObject> picked = null, IList<string> assets = null)
|
||||
{
|
||||
var list = (assets ?? ChartAssets.Where(a => a != Assets.Ponero || Unlock.BlackUnlocked)).ToList();
|
||||
string cur = Selected(key, fallback, list);
|
||||
b.BeginRow(4f);
|
||||
foreach (var a in list)
|
||||
{
|
||||
string asset = a;
|
||||
PledgerSkin.Pick(b, asset, asset == cur, () => { Picked[key] = asset; refresh(); }, picked);
|
||||
}
|
||||
b.End();
|
||||
Add(b, key, cur);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,276 @@
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using Decentralized.Domain;
|
||||
|
||||
namespace Decentralized
|
||||
{
|
||||
/// <summary>
|
||||
/// 用币付款的顾客:每天排队的买家里,按派系(上层 CRC、黑市 CRT、革命派 CRA、下层 PSC)有一小部分改用币结算。
|
||||
/// 成交时在店里扣回刚入账的信用点,换成币进热钱包;赃物的款项不记销赃,改成币带污点(货值 × 赃物热度%)。
|
||||
/// </summary>
|
||||
public static class CoinCustomers
|
||||
{
|
||||
private static readonly HashSet<StoreClient> Marked = new HashSet<StoreClient>();
|
||||
private static int markDay = -1, supportDay = -1;
|
||||
|
||||
public static void Subscribe()
|
||||
{
|
||||
ModHook.OnGenerateCustomerLate += OnGenerate;
|
||||
ModHelper.AddDebugFunction(ModInfo.Id, ModInfo.Name, "Run night (test)", () => Log.Guard("过夜(测试)", () =>
|
||||
{
|
||||
// 走游戏自己的夜间流程(EndNight 会触发本 mod 的夜间结算),再进下一天并开门前的日程
|
||||
// 游戏过夜会清空前柜台,先把自己的东西收进物品栏
|
||||
foreach (var it in EmporiumEntry.Instance.frontInvinvElement.childItems.ToList())
|
||||
if (GeneralHelper.IsItemOwned(it)) GraphUtils.TryAcceptAll(EmporiumEntry.Instance.invElement, it);
|
||||
PlayerStore.Instance.EndNight();
|
||||
StoreStation.Instance.storeEventManager.OnDayEnd(); // 让事件按天数过期
|
||||
StoreStation.Instance.StartDay();
|
||||
Log.Info($"过夜完成,现在是第 {StoreStation.GetDayCounter()} 天");
|
||||
}));
|
||||
ModHelper.AddDebugFunction(ModInfo.Id, ModInfo.Name, "Morning report (test)", () => Log.Guard("晨间日志(测试)", () => StartOfDayUIManager.Instance.ShowMorningReport()));
|
||||
ModHelper.AddDebugFunction(ModInfo.Id, ModInfo.Name, "Newspaper (test)", () => Log.Guard("报纸(测试)", () => NewsUIManager.Instance.ToggleUI()));
|
||||
ModHelper.AddDebugFunction(ModInfo.Id, ModInfo.Name, "Start crackdown (test)", () => Log.Guard("镇压(测试)", () =>
|
||||
{
|
||||
StoreStation.Instance.storeEventManager.ActivateEvent(OperationListSec.Crackdown());
|
||||
Log.Info("镇压事件已激活");
|
||||
}));
|
||||
ModHelper.AddDebugFunction(ModInfo.Id, ModInfo.Name, "Frozen CRT (test)", () => Log.Guard("冻结 CRT(测试)", () =>
|
||||
{
|
||||
var w = Session.Data.Hot;
|
||||
w.Add(Assets.CRT, 1000);
|
||||
double f = w.Freeze(Assets.CRT, Tuning.CrtFreezeShare, StoreStation.GetDayCounter() + Tuning.CrtUnfreezeAfter);
|
||||
Log.Info($"CRT {w.Get(Assets.CRT):0},冻结 {f:0},可动用 {w.Avail(Assets.CRT):0}");
|
||||
}));
|
||||
ModHelper.AddDebugFunction(ModInfo.Id, ModInfo.Name, "Tainted wallet (test)", () => Log.Guard("带污点的钱包(测试)", () =>
|
||||
{
|
||||
var w = Session.Data.Hot;
|
||||
w.Add(Assets.PSC, 100); w.Add(Assets.CRT, 1000); w.Taint += 3000; w.Basis += 2000;
|
||||
Log.Info($"钱包:PSC {w.Get(Assets.PSC):0.##},污点 {w.Taint:0}");
|
||||
}));
|
||||
ModHelper.AddDebugFunction(ModInfo.Id, ModInfo.Name, "Terminal (test)", () => Log.Guard("终端(测试)", TerminalWindow.Open));
|
||||
ModHelper.AddDebugFunction(ModInfo.Id, ModInfo.Name, "Black market +50 rep, restock (test)", () => Log.Guard("黑市(测试)", () =>
|
||||
{
|
||||
StoreReputation.ModReputation("FACTION_BLACK_MARKET", 50);
|
||||
if (!Unlock.IsUnlocked) ModHelper.GetNetworkUpgrade(Unlock.Id)?.Unlock();
|
||||
if (!Unlock.BlackUnlocked) ModHelper.GetNetworkUpgrade(Unlock.BlackId)?.Unlock();
|
||||
if (!Unlock.MixerUnlocked) ModHelper.GetNetworkUpgrade(Unlock.MixerId)?.Unlock();
|
||||
var d = Session.Data;
|
||||
d.Hot.Add(Assets.PSC, 20); d.Hot.Add(Assets.CRT, 3000); d.Hot.Taint += 2000; d.Hot.Basis += 1000;
|
||||
BlackDelivery.Restock(d, StoreStation.GetDayCounter(), true);
|
||||
Log.Info($"黑市:声望 {StoreReputation.GetBMReputation()},上架 {d.Black.Offers.Count} 种:{string.Join(", ", d.Black.Offers.Select(o => o.Item + "×" + o.Qty + "@" + o.Price))},解锁 {Unlock.BlackUnlocked}");
|
||||
}));
|
||||
ModHelper.AddDebugFunction(ModInfo.Id, ModInfo.Name, "Black market sample (test)", () => Log.Guard("黑市抽样(测试)", () =>
|
||||
{
|
||||
var d = Session.Data;
|
||||
int day = StoreStation.GetDayCounter();
|
||||
var vals = new System.Collections.Generic.List<double>();
|
||||
var tech = new System.Collections.Generic.List<double>();
|
||||
for (int i = 0; i < 60; i++)
|
||||
{
|
||||
BlackDelivery.Restock(d, day, true);
|
||||
vals.Add(d.Black.CatalogValue);
|
||||
}
|
||||
var missing = Merchants.Table.SelectMany(kv => kv.Value.Select(e => (kv.Key, e.Id))).Where(x => BlackDelivery.Value(x.Item2) <= 0).Select(x => x.Item1 + ":" + x.Item2).ToList();
|
||||
var costs = Merchants.Table.SelectMany(kv => kv.Value.Select(e => (kv.Key, e.Id))).Select(x => BlackDelivery.Value(x.Item2)).Where(v => v > 0).OrderBy(v => v).ToList();
|
||||
Log.Info("黑市抽样:基础价 >2500 的货:" + string.Join(", ", Merchants.Table.SelectMany(kv => kv.Value.Select(e => (kv.Key, e.Id))).Select(x => (id: x.Item2, v: BlackDelivery.Value(x.Item2))).Where(x => x.v > 2500).Select(x => x.id + "=" + x.v)));
|
||||
Log.Info($"黑市抽样:无法造出或价格为 0 的货 {missing.Count} 个:{string.Join(", ", missing)};基础价中位 {costs[costs.Count / 2]},最高 {costs.Last()}");
|
||||
Log.Info($"黑市抽样:60 周货架总值 平均 {vals.Average():0},最小 {vals.Min():0},最大 {vals.Max():0}");
|
||||
}));
|
||||
ModHelper.AddDebugFunction(ModInfo.Id, ModInfo.Name, "Black market all merchants (test)", () => Log.Guard("黑市全部商家(测试)", () =>
|
||||
{
|
||||
var d = Session.Data;
|
||||
d.Black.RefreshOrders(StoreStation.GetDayCounter(), StoreReputation.GetBMReputation(), d.Rng, BlackDelivery.Value, true);
|
||||
Log.Info($"黑市全部商家(测试):{d.Black.Sellers.Count} 家,货架 {d.Black.Catalog.Count} 种,{string.Join("/", d.Black.Sellers.Select(x => x.Type))}");
|
||||
}));
|
||||
ModHelper.AddDebugFunction(ModInfo.Id, ModInfo.Name, "Black market negative cases (test)", () => Log.Guard("黑市负面场景(测试)", () =>
|
||||
{
|
||||
var d = Session.Data;
|
||||
int day = StoreStation.GetDayCounter();
|
||||
d.Black.RefreshOrders(day, StoreReputation.GetBMReputation(), d.Rng, BlackDelivery.Value, true);
|
||||
var w = d.Hot;
|
||||
w.Add(Assets.CRT, 20000);
|
||||
BmListing First(MerchantType t) => d.Black.Catalog.First(l => d.Black.Sellers[l.Seller].Type == t);
|
||||
// 骗子(老号,接受提前放款):二手矿卡;诚实:全新矿卡;诚实二手卡里夹假卡
|
||||
var scamUsed = First(MerchantType.GpuUsed);
|
||||
var sUsed = d.Black.Sellers[scamUsed.Seller]; sUsed.Scam = true; sUsed.Trades = 120; sUsed.Rating = 97;
|
||||
var honest = First(MerchantType.GpuNew);
|
||||
d.Black.Sellers[honest.Seller].Scam = false; d.Black.Sellers[honest.Seller].Trades = 150;
|
||||
foreach (var s in d.Black.Sellers.Where(x => x.Type == MerchantType.Personal)) s.Scam = true;
|
||||
var fakeL = First(MerchantType.Modules);
|
||||
var fakeCard = new BmListing { Seller = d.Black.Sellers.FindIndex(x => x.Type == MerchantType.Modules), Item = "gpu:RTX70", Kind = GoodKind.Gpu, Level = 2, Model = "RTX70", FakeOf = "RTX60", Health = 55, Price = 500, Qty = 5 };
|
||||
d.Black.Sellers[fakeCard.Seller].Scam = false; d.Black.Sellers[fakeCard.Seller].Trades = 150;
|
||||
d.Black.Catalog.Add(fakeCard);
|
||||
var persL = d.Black.Catalog.First(l => d.Black.Sellers[l.Seller].Type == MerchantType.Personal);
|
||||
d.Black.HoneypotUntil = day + 6;
|
||||
int before = d.Black.Orders.Count;
|
||||
var o1 = d.Black.Place(scamUsed, 1, PayMode.Escrow, w, Assets.CRT, day, Session.Price); // 骗子 + 托管 → 退款
|
||||
var o2 = d.Black.Place(scamUsed, 1, PayMode.Advance, w, Assets.CRT, day, Session.Price); // 骗子 + 提前放款 → 钱没了
|
||||
var o3 = d.Black.Place(fakeCard, 2, PayMode.Escrow, w, Assets.CRT, day, Session.Price); // 假卡
|
||||
var o4 = d.Black.Place(persL, 1, PayMode.Advance, w, Assets.CRT, day, Session.Price); // 个人卖家不接受提前放款 → null
|
||||
var o5 = d.Black.Place(persL, 1, PayMode.Escrow, w, Assets.CRT, day, Session.Price); // 个人卖家(骗子)+ 托管
|
||||
Log.Info($"负面场景:下单 骗子托管={o1 != null} 骗子提前={o2 != null} 假卡={o3 != null} 个人提前={o4 != null}(应为 False)个人托管={o5 != null},蜜罐至第 {d.Black.HoneypotUntil} 天,追查 {d.Black.Traps.Count} 笔,钱包 CRT {w.Get(Assets.CRT):0} 污点 {w.Taint:0}");
|
||||
}));
|
||||
ModHelper.AddDebugFunction(ModInfo.Id, ModInfo.Name, "Black market events (test)", () => Log.Guard("黑市事件(测试)", () =>
|
||||
{
|
||||
var d = Session.Data;
|
||||
int day = StoreStation.GetDayCounter();
|
||||
d.Black.Traps.Add(new BmTrap { Day = day, Amount = 300, Why = "honeypot", Item = "c4" });
|
||||
var w = d.Hot;
|
||||
for (int i = 0; i < 8; i++) d.Black.List("gpu:RTX70", "RTX70", "RTX60", 60, 500, 0.6, w, Assets.CRT, day - 1, Session.Price);
|
||||
var l = d.Black.Catalog.FirstOrDefault();
|
||||
if (l != null)
|
||||
{
|
||||
var o = d.Black.Place(l, 1, PayMode.Escrow, w, Assets.CRT, day, Session.Price);
|
||||
if (o != null) { o.State = OrderState.Ready; o.Controlled = true; }
|
||||
}
|
||||
Log.Info($"黑市事件(测试):追查 300 今晚到期,假卡上架 8 件,受控订单 {d.Black.Orders.Count(x => x.Controlled)} 个");
|
||||
}));
|
||||
ModHelper.AddDebugFunction(ModInfo.Id, ModInfo.Name, "Courier (test)", () => Log.Guard("黑市快递(测试)", () =>
|
||||
{
|
||||
foreach (var o in Session.Data.Black.Orders.Where(x => x.State == OrderState.Pending)) { o.State = OrderState.Ready; }
|
||||
PlayerStore.Instance.currentClientInstance = null;
|
||||
PlayerStore.Instance.storeClientManager.clientStack.Insert(0, BlackDelivery.CreateCourier());
|
||||
PlayerStore.Instance.TryCallNextClient();
|
||||
}));
|
||||
ModHelper.AddDebugFunction(ModInfo.Id, ModInfo.Name, "Courier trap (test)", () => Log.Guard("受控交付(测试)", () =>
|
||||
{
|
||||
foreach (var o in Session.Data.Black.Orders.Where(x => x.State == OrderState.Pending)) { o.State = OrderState.Ready; o.Controlled = true; }
|
||||
PlayerStore.Instance.currentClientInstance = null;
|
||||
PlayerStore.Instance.storeClientManager.clientStack.Insert(0, BlackDelivery.CreateCourier());
|
||||
PlayerStore.Instance.TryCallNextClient();
|
||||
}));
|
||||
ModHelper.AddDebugFunction(ModInfo.Id, ModInfo.Name, "Coin buyer forged (test)", () => { ForceFake = true; CoinBuyerTest(); });
|
||||
ModHelper.AddDebugFunction(ModInfo.Id, ModInfo.Name, "Coin buyer (test)", () => { ForceFake = false; CoinBuyerTest(); });
|
||||
}
|
||||
|
||||
private static bool ForceFake;
|
||||
|
||||
private static void CoinBuyerTest() => Log.Guard("用币付款顾客(测试)", () =>
|
||||
{
|
||||
var c = new StoreClient
|
||||
{
|
||||
identifier = "pd_coin_test", displayName = "Coin buyer", spriteName = SpriteDict.GetRandomScavSpriteName(),
|
||||
clientFaction = "FACTION_BLACK_MARKET", useClientBudget = true, clientIntent = StoreClient.ClientIntent.BUY,
|
||||
canClientExposeFeature = ClientCanExposeFunc.BasicClientExposeCapacity,
|
||||
};
|
||||
c.SetBudget(5000);
|
||||
c.clientBuyingTagList.Add("SEED");
|
||||
c.mainDialogue.SetText(c.displayName, "CRT.").SetEndAction(() => { });
|
||||
c.AddBasicDialog();
|
||||
c.CompleteClientCreation();
|
||||
Mark(c, Assets.CRT, ForceFake);
|
||||
Log.Info($"用币付款顾客(测试)已设置,钱包污点 {Session.Data.Hot.Taint:0.##},当前顾客 {PlayerStore.Instance.currentClientInstance?.GetClientBlueprint()?.identifier},队列 {PlayerStore.Instance.storeClientManager.clientStack.Count} 人");
|
||||
PlayerStore.Instance.currentClientInstance = null; // 测试:丢掉在场的顾客(开局的高利贷者不可遣散)
|
||||
PlayerStore.Instance.storeClientManager.clientStack.Insert(0, c);
|
||||
PlayerStore.Instance.TryCallNextClient();
|
||||
// 把后柜里的种子都标成赃物(热度 50%),买走后钱包的污点应为成交额的一半
|
||||
foreach (var it in EmporiumEntry.Instance.backInvinvElement.childItems)
|
||||
if (it.IsTag("SEED")) it.ModifyTag("STOLEN_VALUE_INT", t => t.Enable().SetInt(50));
|
||||
});
|
||||
|
||||
public static void Unsubscribe() => ModHook.OnGenerateCustomerLate -= OnGenerate;
|
||||
|
||||
private static void OnGenerate(StoreClientManager manager)
|
||||
{
|
||||
if (Session.Data == null || !Unlock.IsUnlocked || !Session.Data.Connected) return; // 没有连接钱包就没有用币付款的顾客
|
||||
Log.Guard("用币付款", () =>
|
||||
{
|
||||
int day = StoreStation.GetDayCounter();
|
||||
if (day != markDay) { Marked.Clear(); markDay = day; }
|
||||
// 假客服:一天最多一次
|
||||
if (day >= Tuning.ScamMinDay && supportDay != day)
|
||||
{
|
||||
supportDay = day;
|
||||
if (Session.Data.Rng.Chance(Tuning.FakeSupportChance)) manager.AddClient(FakeSupport());
|
||||
}
|
||||
foreach (var c in manager.clientStack)
|
||||
{
|
||||
if (c == null || c.isSecurity || Marked.Contains(c) || c.clientIntent != StoreClient.ClientIntent.BUY || c.isNoContributeToEvidence) continue;
|
||||
Marked.Add(c);
|
||||
string asset = CoinPayment.AssetFor(c.clientFaction);
|
||||
if (asset == null || !Session.Data.Rng.Chance(CoinPayment.Chance(asset))) continue;
|
||||
Mark(c, asset, day >= Tuning.ScamMinDay && Session.Data.Rng.Chance(Tuning.FakeTransferShare));
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 标成用币付款的顾客。开口先说用什么币付:正常的说"链上确认要一会儿";骗子(伪造转账)说"已经转了,给你看截图,快给货"——
|
||||
/// 成交后信用点照样被扣回,币却不会到账。玩家能做的就是听清这句话,不卖给他。
|
||||
/// </summary>
|
||||
private static void Mark(StoreClient c, string asset, bool fake)
|
||||
{
|
||||
var before = c.onItemBought;
|
||||
double total = 0; // 这位顾客这一单一共付了多少币
|
||||
c.isNoContributeToEvidence = true;
|
||||
var intro = new Dialogue().SetText(c.displayName, L.T(fake ? "coinpay.intro.fake" : "coinpay.intro", asset));
|
||||
intro.SetNextDialogue(c.mainDialogue);
|
||||
c.mainDialogue = intro;
|
||||
c.onItemBought = (item, cost) =>
|
||||
{
|
||||
before?.Invoke(item, cost);
|
||||
Log.Guard("用币付款成交", () =>
|
||||
{
|
||||
if (fake) { FakePay(c, asset, item, cost); total += cost / Session.Price(asset); }
|
||||
else total += Pay(c, asset, item, cost);
|
||||
Say(c, asset, total);
|
||||
});
|
||||
};
|
||||
}
|
||||
|
||||
/// <summary>伪造转账:信用点扣回(顾客没真付),币不会到账,晨间日志说明。</summary>
|
||||
private static void FakePay(StoreClient client, string asset, GameItem item, int cost)
|
||||
{
|
||||
if (cost <= 0) return;
|
||||
ModHelper.AddCredit(-cost, false);
|
||||
Session.Data.FakePaidToday.Add(L.T("coinpay.fake.entry", client.displayName, item.name, cost));
|
||||
Log.Info($"伪造转账:{client.displayName} 拿走 {item.name}({cost} 信用点),{asset} 不会到账");
|
||||
}
|
||||
|
||||
/// <summary>假客服:自称 Poinbase 客服,说账户被风控,要把 CRC 转到"安全地址"。Poinbase 从不上门,也从不要求转账;转过去的币就没了。</summary>
|
||||
public static StoreClient FakeSupportForTest() => FakeSupport();
|
||||
|
||||
private static StoreClient FakeSupport()
|
||||
{
|
||||
var d = Session.Data;
|
||||
string addr = ChainAddress.Make(d.Rng.NextUInt());
|
||||
d.Scams.ScamAddrs.Add(addr);
|
||||
int amount = 100 * d.Rng.Range(3, 15);
|
||||
var c = new StoreClient
|
||||
{
|
||||
identifier = "pd_fake_support", displayName = L.T("scam.support.name"), spriteName = SpriteDict.GetRandomUpperSpriteName(),
|
||||
clientIntent = StoreClient.ClientIntent.DIALOGUE,
|
||||
};
|
||||
c.mainDialogue.SetText(c.displayName, L.T("scam.support.1")).NextDialogue()
|
||||
.SetText(c.displayName, L.T("scam.support.2", amount, addr)).NextDialogue()
|
||||
.SetText(c.displayName, L.T("scam.support.3"));
|
||||
ModHelper.SetClientSource(c, ModInfo.Id);
|
||||
c.AddBasicDialog();
|
||||
c.CompleteClientCreation();
|
||||
Log.Info($"假客服上门:要 {amount} CRC 转到 {addr}");
|
||||
return c;
|
||||
}
|
||||
|
||||
/// <summary>成交后顾客说的话:告诉玩家这单是币到账,不是信用点。</summary>
|
||||
private static void Say(StoreClient client, string asset, double total)
|
||||
{
|
||||
client.acceptDealDialogue = new Dialogue().SetText(client.displayName, L.T("coinpay.line", Fmt.Num(total), asset));
|
||||
client.acceptDealDialogue.priority = 4;
|
||||
client.acceptDealDialoguePlayed = false;
|
||||
}
|
||||
|
||||
private static double Pay(StoreClient client, string asset, GameItem item, int cost)
|
||||
{
|
||||
var d = Session.Data;
|
||||
double price = Session.Price(asset);
|
||||
if (cost <= 0 || price <= 0) return 0;
|
||||
int heat = item.IsTag("STOLEN_VALUE_INT") ? item.GetTagReadonly("STOLEN_VALUE_INT").GetInt() : 0;
|
||||
ModHelper.AddCredit(-cost, false);
|
||||
double qty = CoinPayment.Receive(d.Hot, asset, cost, price, heat);
|
||||
d.Chain(ChainAddress.Make(d.Rng.NextUInt()), d.Hot.Address, asset, qty);
|
||||
d.CoinSalesToday += cost;
|
||||
Log.Info($"用币付款:{item.name} {cost} 信用点 → {qty:0.####} {asset},污点 +{cost * heat / 100.0:0}");
|
||||
return qty;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -7,13 +7,19 @@ namespace Decentralized
|
||||
{
|
||||
public const string Id = "probably_decentralized";
|
||||
public const string Name = "Probably Decentralized";
|
||||
public const string Version = "0.1.0";
|
||||
public const string Version = "1.1.0";
|
||||
}
|
||||
|
||||
/// <summary>本地化:游戏的 mod 本地化表(ModFiles/Localization/*.csv),当前语言缺失时回退英文。</summary>
|
||||
public static class L
|
||||
{
|
||||
public static string T(string key, params object[] args) => ModHelper.GetLocalized(ModInfo.Id, key, args);
|
||||
|
||||
/// <summary>当前游戏语言代码(en zh de fr es pl ru ja)。</summary>
|
||||
public static string Code => LocHelper.GetCurrentLocaleCode() ?? "en";
|
||||
|
||||
/// <summary>译文普遍比中英文长的语言:表格列宽、操作键区按此放宽。</summary>
|
||||
public static bool Wide { get { var c = Code; return c == "de" || c == "fr" || c == "es" || c == "pl" || c == "ru"; } }
|
||||
}
|
||||
|
||||
public static class Log
|
||||
@@ -29,6 +35,13 @@ namespace Decentralized
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>系统剪贴板(游戏里的输入框也能 Ctrl+V)。</summary>
|
||||
public static class Clipboard
|
||||
{
|
||||
public static void Copy(string s) => GUIUtility.systemCopyBuffer = s ?? "";
|
||||
public static string Paste() => (GUIUtility.systemCopyBuffer ?? "").Trim();
|
||||
}
|
||||
|
||||
public static class Fmt
|
||||
{
|
||||
public static string Num(double v) => Math.Abs(v) >= 100 ? v.ToString("N0") : Math.Abs(v) >= 1 ? v.ToString("0.##") : v.ToString("0.####");
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using UnityEngine;
|
||||
using Decentralized.Domain;
|
||||
|
||||
namespace Decentralized
|
||||
@@ -15,6 +16,195 @@ namespace Decentralized
|
||||
ModHook.OnPlaceInventorInventoryItemLate += OnPlace;
|
||||
// 开发者模式(F9)里的测试入口:像到了杰克逊店里一样,清空并扩大柜台后上货
|
||||
ModHelper.AddDebugFunction(ModInfo.Id, ModInfo.Name, "Give rig x3 (test)", () => { for (int i = 0; i < 3; i++) Items.Give(ModHelper.SpawnItem(Items.Rig)); });
|
||||
ModHelper.AddDebugFunction(ModInfo.Id, ModInfo.Name, "Used cards x4 (test)", () =>
|
||||
{
|
||||
var rng = Session.Data.Rng;
|
||||
Items.Give(Items.NewCard("RTX80", 40, null, rng));
|
||||
Items.Give(Items.NewCard("RTX80", 70, "RTX60", rng));
|
||||
Items.Give(Items.NewCard("RX800", 30, "RX70", rng));
|
||||
Items.Give(Items.NewCard("RX900", 90, "RX70", rng));
|
||||
});
|
||||
ModHelper.AddDebugFunction(ModInfo.Id, ModInfo.Name, "Dump inspection UI (test)", () => Log.Guard("检视界面结构", () =>
|
||||
{
|
||||
var sb = new System.Text.StringBuilder("\n");
|
||||
void Walk(Transform t, int depth)
|
||||
{
|
||||
var rt = t as RectTransform;
|
||||
var img = t.GetComponent<UnityEngine.UI.Image>();
|
||||
sb.AppendLine($"{new string(' ', depth * 2)}{t.name} active={t.gameObject.activeSelf} pos={t.localPosition} size={(rt != null ? rt.sizeDelta.ToString() : "-")} scale={t.localScale}{(img != null ? " img=" + (img.sprite != null ? img.sprite.name : "null") : "")}");
|
||||
if (depth < 5) foreach (Transform c in t) Walk(c, depth + 1);
|
||||
}
|
||||
var m = InspectionUIManager.Instance;
|
||||
var ci = PlayerStore.Instance.currentClientInstance;
|
||||
sb.AppendLine("当前顾客:" + (ci == null ? "无" : ci.GetClientBlueprint().identifier + " 意图 " + ci.GetClientBlueprint().clientIntent));
|
||||
sb.AppendLine("检视物品:" + (m.currentInspectingItem?.identifier ?? "无") + " APPRAISAL=" + (m.currentInspectingItem?.IsTag("APPRAISAL_ITEM") ?? false));
|
||||
Walk(m.panel.transform, 0);
|
||||
Log.Info(sb.ToString());
|
||||
}));
|
||||
ModHelper.AddDebugFunction(ModInfo.Id, ModInfo.Name, "Edit claim + offer to buyer (test)", () => Log.Guard("卖出侧测试", () =>
|
||||
{
|
||||
var rng = Session.Data.Rng;
|
||||
// 自己的一张真卡:标签机改成旗舰型号并把成色说成没问题,再摆给一位买家
|
||||
var item = Items.NewCard("RTX70", 55, null, rng);
|
||||
Items.Give(item);
|
||||
var u = Items.ToUnit(item);
|
||||
var c = Claim.Truth(u); c.Model = "RTX90"; c.Fan = 0; c.Fingers = 0; c.Bracket = 0; c.Sticker = 0;
|
||||
item.EnableTag(Items.EditedTag);
|
||||
Items.SetClaim(item, c, 0);
|
||||
var client = new StoreClient { identifier = "pd_test_buyer", displayName = "买家", spriteName = SpriteDict.GetRandomScavSpriteName(), clientIntent = StoreClient.ClientIntent.BUY };
|
||||
client.CompleteClientCreation();
|
||||
PlayerStore.Instance.currentClientInstance = StoreClientInstance.CreateClientInstance(client);
|
||||
Log.Info($"测试:卡 #{item.uniqueId} 说法 {c.Encode()},真实 {Claim.Truth(u).Encode()},价格 {item.unitValue},信誉前");
|
||||
Items.OfferForTest(item);
|
||||
Log.Info($"测试:验货后 Exposed={Items.Exposed(item)} 价格 {item.unitValue}");
|
||||
}));
|
||||
ModHelper.AddDebugFunction(ModInfo.Id, ModInfo.Name, "Buy scam card (test)", () => Log.Guard("买入侧测试", () =>
|
||||
{
|
||||
var rng = Session.Data.Rng;
|
||||
var item = Items.NewCard("RTX90", 60, "RTX60", rng, DealerKind.Scammer, 0);
|
||||
long before = item.unitValue;
|
||||
GeneralHelper.SetItemOwned(item, true);
|
||||
Items.Refresh(item);
|
||||
Items.Give(item);
|
||||
Log.Info($"买入测试:卡 #{item.uniqueId} 买前报价 {before},买下后价值 {item.unitValue},真实 {CardValue.True(Items.ToUnit(item))},说法 {(Items.GetClaim(item)?.Encode() ?? "无")}");
|
||||
}));
|
||||
ModHelper.AddDebugFunction(ModInfo.Id, ModInfo.Name, "Poinbase +5000 CRC, unlock (test)", () => Log.Guard("永续测试", () =>
|
||||
{
|
||||
var d = Session.Data;
|
||||
d.Poinbase.Add(Assets.CRC, 5000); d.Poinbase.Basis += 5000;
|
||||
if (!Unlock.IsUnlocked) ModHelper.GetNetworkUpgrade(Unlock.Id)?.Unlock();
|
||||
Log.Info($"测试:Poinbase CRC {d.Poinbase.Get(Assets.CRC):0},解锁 {Unlock.IsUnlocked}");
|
||||
}));
|
||||
ModHelper.AddDebugFunction(ModInfo.Id, ModInfo.Name, "Give ASIC M1/M2/M3 (test)", () => { foreach (var m in new[] { "M1", "M2", "M3" }) Items.Give(AsicItems.New(m, 100)); for (int i = 0; i < 4; i++) Items.Give(ModHelper.SpawnItem("rare_electronic")); });
|
||||
ModHelper.AddDebugFunction(ModInfo.Id, ModInfo.Name, "Era in 2 days (test)", () => { var n = Session.Data.Network; int day = StoreStation.GetDayCounter(); n.EraDay = day + 2; n.EraWarnDay = day; n.EraWarned = false; n.EraDone = false; Log.Info($"测试:矿机时代第 {n.EraDay} 天,NPC 耗电 {n.NpcKj}"); });
|
||||
ModHelper.AddDebugFunction(ModInfo.Id, ModInfo.Name, "Predict: refill all kinds (test)", () => Log.Guard("预测测试", () =>
|
||||
{
|
||||
var d = Session.Data; int day = StoreStation.GetDayCounter();
|
||||
d.Predict.Markets.Clear();
|
||||
PredictGame.Morning(d, day); var made = new List<PredictMarket>(); for (int i = 0; i < 4; i++) made.AddRange(d.Predict.Refill(day, d.Rng, PredictGame.Candidates(day)));
|
||||
Log.Info($"测试:新开 {made.Count} 个预测盘口(不看解锁日)");
|
||||
}));
|
||||
ModHelper.AddDebugFunction(ModInfo.Id, ModInfo.Name, "Predict: add era and CRA (test)", () =>
|
||||
{
|
||||
var d = Session.Data; int day = StoreStation.GetDayCounter(); var bk = d.Predict;
|
||||
bk.Markets.Add(PredictMarket.Create(++bk.Seq, PredictKind.Era, "era", L.T("predict.era"), 0, day, day + 1, day + 3, PredictMath.EraProb(day, day + 1, day + 3, -1) + 0.05));
|
||||
double h = 1 - System.Math.Pow(1 - Tuning.CraSpiralWeekly, 1.0 / 7);
|
||||
bk.Markets.Add(PredictMarket.Create(++bk.Seq, PredictKind.Cra, "cra", "CRA", 0, day, day + 1, day + 3, PredictMath.CraWarnProb(d.Stable.Cushion, Stablecoins.CushionDrain(Tuning.CraNpcStake + d.Staking.Earning, d.Stable.CraRate), day, day + 1, day + 3, h)));
|
||||
Log.Info($"测试:矿机时代 {d.Network.EraDay},CRA 储备 {d.Stable.Reserve:0}(R/S {d.Stable.Ratio:0.00})");
|
||||
});
|
||||
ModHelper.AddDebugFunction(ModInfo.Id, ModInfo.Name, "Informant: queue power shortage in 3 days (test)", () => Log.Guard("线人测试", () =>
|
||||
{
|
||||
StoreStation.Instance.storeEventManager.QueueFuturEvent(EventListNormal.CreatePowerShortage(), 3, true);
|
||||
Log.Info("测试:停电 3 天后(已知)");
|
||||
}));
|
||||
ModHelper.AddDebugFunction(ModInfo.Id, ModInfo.Name, "Scams: airdrops + pools + wick (test)", () => Log.Guard("骗局测试", () =>
|
||||
{
|
||||
var d = Session.Data; int day = StoreStation.GetDayCounter();
|
||||
var assets = new[] { Assets.CRT, Assets.PSC, Assets.CRC, Assets.CRA };
|
||||
for (int i = 0; i < 4; i++) d.Scams.NewAirdrop(day, d.Rng, assets);
|
||||
while (d.Scams.Pools.Count(p => !p.Closed) < Tuning.YieldPoolMax) d.Scams.NewPool(day, d.Rng);
|
||||
d.Market.Wick = 0; double w = 0; for (int i = 0; i < 200 && w == 0; i++) w = d.Market.TryWick(d.Rng, day);
|
||||
Log.Info($"测试:空投 {string.Join(",", d.Scams.Airdrops.Select(a => a.Name + (a.Scam ? "*" : "")))};池子 {string.Join(",", d.Scams.Pools.Select(p => p.Name + (p.Scam ? "*" : "")))};插针 {w:0.000} 回去 {d.Market.WickBack:0.00}");
|
||||
}));
|
||||
ModHelper.AddDebugFunction(ModInfo.Id, ModInfo.Name, "Scams: fake support now (test)", () => Log.Guard("假客服测试", () =>
|
||||
{
|
||||
var m = PlayerStore.Instance.storeClientManager;
|
||||
var c = CoinCustomers.FakeSupportForTest();
|
||||
PlayerStore.Instance.currentClientInstance = null;
|
||||
m.clientStack.Insert(0, c);
|
||||
PlayerStore.Instance.TryCallNextClient();
|
||||
}));
|
||||
ModHelper.AddDebugFunction(ModInfo.Id, ModInfo.Name, "Chart: run market 30 days (test)", () => Log.Guard("K 线测试", () =>
|
||||
{
|
||||
// 用真实的行情过程往前跑 30 天,记录蜡烛(会改动这一局的 PSC 价格,只在测试存档用)
|
||||
var d = Session.Data; int day0 = StoreStation.GetDayCounter() - 30; var none = new List<MarketEvent>();
|
||||
d.Candles.Series.Clear();
|
||||
for (int k = day0; k < day0 + 30; k++)
|
||||
{
|
||||
d.Market.Open(none, d.Rng, k); CandleChart.Morning(d, k);
|
||||
double wh = d.Market.Whale(d.Rng); d.Candles.Tick(Assets.PSC, k, d.Market.Price, wh);
|
||||
if (d.Market.TryWick(d.Rng, k) != 0) CandleChart.Touch(d, k, Assets.PSC, Assets.Ponero);
|
||||
if (d.Rng.Chance(0.3)) { double v = d.Rng.Range(500.0, 4000.0); bool buy = d.Rng.Chance(0.5); if (buy) d.Market.Main.BuyBase(v); else d.Market.Main.SellBase(v / d.Market.Price); d.Candles.Tick(Assets.PSC, k, d.Market.Price, v, true); }
|
||||
d.Market.UndoWick(k); CandleChart.Close(d, k);
|
||||
d.Stable.Night(k, d.Rng, d.Staking.Earning);
|
||||
d.Market.Night(none, d.Rng, k, Session.Price); d.Market.UpdateSupply(k);
|
||||
}
|
||||
CandleChart.Morning(d, day0 + 30);
|
||||
Log.Info($"测试:K 线 {d.Candles.Of(Assets.PSC).Count} 根,PSC {d.Market.Price:0.00}");
|
||||
}));
|
||||
ModHelper.AddDebugFunction(ModInfo.Id, ModInfo.Name, "Story: Serpico to Revolution, Eleanor leaks, Lun arrested (test)", () =>
|
||||
{
|
||||
var cd = PlayerStore.GetStoreClientData();
|
||||
cd.serpicoDocumentChoice = SerpicoStoryline.CHOICE_REVOLUTION; cd.eleanorDriveChoice = 2; cd.officerLunArrested = true;
|
||||
Log.Info("测试:剧情选择已设置(革命军 / 泄露 / 伦警官被捕),今晚生效");
|
||||
});
|
||||
ModHelper.AddDebugFunction(ModInfo.Id, ModInfo.Name, "Tumbler: next visit now (test)", () => Log.Guard("Tumbler 测试", () =>
|
||||
{
|
||||
// 把 Tumbler 的下一次上门挪到今天,并立刻叫进来
|
||||
var t = Session.Data.Story.Tumbler; int day = StoreStation.GetDayCounter();
|
||||
if (t.StartDay < 0) t.StartDay = day;
|
||||
t.StartDay = day - Tumbler.Offsets[System.Math.Min(t.Stage, Tumbler.Offsets.Length - 1)]; t.VisitedDay = -1;
|
||||
PlayerStore.Instance.currentClientInstance = null;
|
||||
var m = PlayerStore.Instance.storeClientManager;
|
||||
TumblerStory.ForceVisit(m);
|
||||
PlayerStore.Instance.TryCallNextClient();
|
||||
}));
|
||||
ModHelper.AddDebugFunction(ModInfo.Id, ModInfo.Name, "Lower-level rep +30 (test)", () => StoreReputation.ModReputation(StoreReputation.FACTION_LOWER_LEVEL, 30));
|
||||
ModHelper.AddDebugFunction(ModInfo.Id, ModInfo.Name, "Dump crimes and reputation (test)", () => Log.Guard("罪证与声望", () =>
|
||||
{
|
||||
var sd = PlayerStore.Instance.secData;
|
||||
var crimes = string.Join(",", sd.crimeTypes.Select((c, i) => c + " " + sd.crimeAmount[i]));
|
||||
string Rep(string f) => f + " " + (StoreReputation.GetStoreReputation(f)?.GetReputation().ToString() ?? "-");
|
||||
Log.Info($"测试:罪证 [{crimes}],证据 {sd.evidenceLevel};声望 {Rep(StoreReputation.FACTION_LOWER_LEVEL)},{Rep(StoreReputation.FACTION_SECURITY)},{Rep(StoreReputation.FACTION_BLACK_MARKET)};现金 {PlayerStore.Instance.playerCash}");
|
||||
}));
|
||||
ModHelper.AddDebugFunction(ModInfo.Id, ModInfo.Name, "Scams: phishing approval + scam pool (test)", () => Log.Guard("骗局补测", () =>
|
||||
{
|
||||
// 当前钱包:一个钓鱼授权(明晚转走 CRT);一个必然是骗局的池子(存 500)和一个正规的时间锁池子(存 500 并申请取出)
|
||||
var d = Session.Data; int day = StoreStation.GetDayCounter(); var w = d.Hot;
|
||||
d.Scams.Pools.Clear(); d.Scams.Approvals.Clear();
|
||||
d.Scams.Approvals.Add(new Approval { Id = ++d.Scams.Seq, Wallet = w.Address, Asset = Assets.CRT, Spender = "P0inbase", Limit = double.PositiveInfinity, Scam = true, DrainDay = day + 1 });
|
||||
var bad = new YieldPool { Id = ++d.Scams.Seq, Name = "Test Scam", OpenDay = day - 1, Rate = 0.03, Reserve = 9999, Cap = 1e6, Scam = true };
|
||||
var ok = new YieldPool { Id = ++d.Scams.Seq, Name = "Test Lock", OpenDay = day - 1, Rate = 0.01, Reserve = 9999, Cap = 1e6, Timelock = true };
|
||||
d.Scams.Pools.Add(bad); d.Scams.Pools.Add(ok);
|
||||
d.Scams.Deposit(bad, w, 500, Session.Price); d.Scams.Deposit(ok, w, 500, Session.Price); d.Scams.Withdraw(ok, w, day);
|
||||
Log.Info($"测试:钓鱼授权 #{d.Scams.Approvals[0].Id}(明晚转走 CRT {w.Get(Assets.CRT):0}),骗局池存 500,时间锁池取款第 {day + Tuning.YieldLockDays} 天到账;CRC {w.Get(Assets.CRC):0}");
|
||||
}));
|
||||
ModHelper.AddDebugFunction(ModInfo.Id, ModInfo.Name, "Perp: PSC long 1000 x2 (test)", () => Log.Guard("永续测试", () =>
|
||||
{
|
||||
var d = Session.Data; d.Poinbase.Add(Assets.CRC, 2000);
|
||||
// 先让价格偏离 7 日均线,资金费才不为零:补几个历史标记价
|
||||
d.Perps.Marks["PSC"] = new System.Collections.Generic.List<double> { d.Market.Price * 0.8, d.Market.Price * 0.8, d.Market.Price * 0.8 };
|
||||
var res = d.Perps.Open(d.Poinbase, "PSC", true, 1000, 2, d.Market.Price, StoreStation.GetDayCounter(), Session.Price);
|
||||
Log.Info($"测试:永续开多 {res},现价 {d.Market.Price:0.00}");
|
||||
}));
|
||||
ModHelper.AddDebugFunction(ModInfo.Id, ModInfo.Name, "Give key drive (test)", () => Items.Give(ModHelper.SpawnItem(Items.KeyDrive)));
|
||||
ModHelper.AddDebugFunction(ModInfo.Id, ModInfo.Name, "Give GPU guide (test)", () => Items.Give(ModHelper.SpawnItem(Items.Guide)));
|
||||
ModHelper.AddDebugFunction(ModInfo.Id, ModInfo.Name, "Predict: window = tomorrow (test)", () => { foreach (var m in Session.Data.Predict.Markets) { m.FromDay = m.ToDay = StoreStation.GetDayCounter() + 1; } Log.Info("测试:所有盘口窗口改成明天"); });
|
||||
ModHelper.AddDebugFunction(ModInfo.Id, ModInfo.Name, "Perp fund 0 (test)", () => { Session.Data.Perps.InsuranceFund = 0; Log.Info("测试:保险基金清零"); });
|
||||
ModHelper.AddDebugFunction(ModInfo.Id, ModInfo.Name, "SPARK x0.3 (test)", () => { var st = Session.Data.Stable; st.Spark *= 0.3; Log.Info($"测试:SPARK 价格 {st.Spark:0.00}"); });
|
||||
ModHelper.AddDebugFunction(ModInfo.Id, ModInfo.Name, "Wallet gift: CRC, CRA, PSC (test)", () => { var w = Session.Data.Hot; w.Add(Assets.CRA, 1000); w.Add(Assets.CRC, 1000); w.Add(Assets.CRT, 3000); w.Add(Assets.PSC, 20); w.Add(Assets.SPARK, 300); w.Basis += 5000; Log.Info($"测试:{WalletWindow.NameOf(w)} CRA {w.Get(Assets.CRA):0}"); });
|
||||
ModHelper.AddDebugFunction(ModInfo.Id, ModInfo.Name, "Poinbase gift: CRC, PSC (test)", () => { var pb = Session.Data.Poinbase; pb.Add(Assets.CRC, 5000); pb.Add(Assets.PSC, 30); pb.Basis += 8000; Log.Info($"测试:Poinbase CRC {pb.Get(Assets.CRC):0}"); });
|
||||
ModHelper.AddDebugFunction(ModInfo.Id, ModInfo.Name, "CRA spiral warning (test)", () =>
|
||||
{
|
||||
var st = Session.Data.Stable; int day = StoreStation.GetDayCounter();
|
||||
st.CraWarnDay = day; st.CraEventDay = day + 3;
|
||||
Log.Info($"测试:CRA 预兆今天,挪用日第 {st.CraEventDay} 天");
|
||||
});
|
||||
ModHelper.AddDebugFunction(ModInfo.Id, ModInfo.Name, "Give terminal (test)", () => { Items.Give(ModHelper.SpawnItem(Items.Terminal)); });
|
||||
ModHelper.AddDebugFunction(ModInfo.Id, ModInfo.Name, "Hardware wallets (test)", () => { Items.Give(Items.NewHwWallet(false)); Items.Give(Items.NewHwWallet(true)); Log.Info("测试:给了一个正品、一个被投毒的硬件钱包"); });
|
||||
ModHelper.AddDebugFunction(ModInfo.Id, ModInfo.Name, "Chain drama (test)", () => Log.Guard("链上事件测试", () =>
|
||||
{
|
||||
// 今天拥堵;当前钱包最近转出过的地址立刻收到相似地址的 0 币转入;报纸和论坛各来一条钓鱼
|
||||
var d = Session.Data;
|
||||
int day = StoreStation.GetDayCounter();
|
||||
d.CongestedFrom = day; d.CongestedUntil = day + 1;
|
||||
var last = d.Hot.History.FirstOrDefault(r => !r.In);
|
||||
if (last != null) d.Chain(ChainAddress.Lookalike(last.Addr, d.Rng), d.Hot.Address, Assets.PSC, 0, zero: true);
|
||||
string fake = ChainAddress.Make(d.Rng.NextUInt());
|
||||
News.Show("pd_news_phish_test_" + day, L.T("news.phish.title"), L.T("news.phish.desc", fake), 2);
|
||||
d.Black.Forum.Add("phish:" + ChainAddress.Make(d.Rng.NextUInt()));
|
||||
Log.Info($"测试:拥堵到第 {d.CongestedUntil} 天;投毒 {(last != null ? last.Addr : "无转出记录")};钓鱼 {fake}");
|
||||
}));
|
||||
ModHelper.AddDebugFunction(ModInfo.Id, ModInfo.Name, "Dr. Jackson stock (test)", () =>
|
||||
{
|
||||
EmporiumEntry.Instance.ClearFrontInv();
|
||||
@@ -43,6 +233,13 @@ namespace Decentralized
|
||||
bool ok = PlayerStore.Instance.TryAddDirectSellingItemToTable(item);
|
||||
placed.Add(ok ? $"{kind}#{item.uniqueId}" : kind + "(柜台已满)");
|
||||
}
|
||||
// 硬件钱包(正品):钱包和手上的硬件钱包加起来还没到上限时,有一定概率上一个
|
||||
int wallets = Session.Data.Wallets.Count + (owned?.Count(i => i.identifier == Items.HwWallet) ?? 0);
|
||||
if (wallets < Tuning.WalletMax && Session.Data.Rng.Chance(Tuning.WalletJacksonChance))
|
||||
{
|
||||
var hw = Items.NewHwWallet(false);
|
||||
placed.Add(PlayerStore.Instance.TryAddDirectSellingItemToTable(hw) ? $"硬件钱包#{hw.uniqueId}" : "硬件钱包(柜台已满)");
|
||||
}
|
||||
Log.Info("杰克逊博士上货:" + string.Join(",", placed));
|
||||
});
|
||||
}
|
||||
|
||||
@@ -0,0 +1,111 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using Decentralized.Domain;
|
||||
using UnityEngine;
|
||||
|
||||
namespace Decentralized
|
||||
{
|
||||
/// <summary>
|
||||
/// Poinbase 的出金:转到钱包地址。托管账户发起,几秒钟的确认动画(模拟交易所触发合约执行)走完才落地;
|
||||
/// 手续费固定中间档,从转出的币里扣。动画走完前币还在账户里,中途存档、退出都不会丢币。
|
||||
/// 地址格式或校验位不对拒绝;自己的钱包到账;别的格式正确的地址按黑洞处理(币就没了)。
|
||||
/// </summary>
|
||||
internal static class Funds
|
||||
{
|
||||
internal sealed class Tx
|
||||
{
|
||||
public int Id, Confs;
|
||||
public string Asset, To;
|
||||
public double Amount, Fee;
|
||||
public float Start, Total;
|
||||
public bool Finished;
|
||||
}
|
||||
|
||||
internal static readonly List<Tx> Active = new List<Tx>();
|
||||
private static int seq;
|
||||
|
||||
/// <summary>地址检查:返回 null 表示可以转,否则是错误文案的键。</summary>
|
||||
internal static string Check(string to)
|
||||
{
|
||||
var d = Session.Data;
|
||||
to = ChainAddress.Normalize(to ?? "");
|
||||
if (!ChainAddress.Valid(to)) return "funds.err.addr";
|
||||
if (ChainAddress.Same(to, d.Address("poinbase"))) return "funds.err.self";
|
||||
if (d.Own(to) == null && WalletWindow.Known(to)) return "funds.err.known";
|
||||
return null;
|
||||
}
|
||||
|
||||
private static bool Congested
|
||||
{
|
||||
get { var d = Session.Data; int day = StoreStation.GetDayCounter(); return day >= d.CongestedFrom && day <= d.CongestedUntil; }
|
||||
}
|
||||
|
||||
/// <summary>开始一笔出金。余额不足或手续费吃掉全部数额返回错误键,成功返回 null。</summary>
|
||||
internal static string Start(string asset, double amount, string to)
|
||||
{
|
||||
var d = Session.Data;
|
||||
var err = Check(to);
|
||||
if (err != null) return err;
|
||||
var pb = d.Poinbase;
|
||||
if (pb.Avail(asset) + 1e-9 < amount) return pb.Frozen.ContainsKey(asset) ? "msg.frozen" : "msg.balance";
|
||||
double price = Session.Price(asset);
|
||||
double fee = price > 0 ? TxRules.FeeCredits(FeeTier.Normal, Congested, d.Gas) / price : 0;
|
||||
if (fee >= amount) return "funds.err.fee";
|
||||
double value = amount * price;
|
||||
int confs = TxRules.Confirmations(value);
|
||||
Active.Add(new Tx
|
||||
{
|
||||
Id = ++seq, Asset = asset, To = ChainAddress.Normalize(to), Amount = amount, Fee = fee, Confs = confs,
|
||||
Start = Time.unscaledTime, Total = (float)(Tuning.FundsBaseSecs + confs * Tuning.FundsConfSecs),
|
||||
});
|
||||
WalletDriver.Ensure();
|
||||
return null;
|
||||
}
|
||||
|
||||
internal static float Progress(Tx t) => t.Total <= 0 ? 1 : Mathf.Clamp01((Time.unscaledTime - t.Start) / t.Total);
|
||||
|
||||
internal static int Conf(Tx t) => Math.Max(1, Math.Min(t.Confs, 1 + (int)((Time.unscaledTime - t.Start) / Math.Max(0.01f, t.Total) * t.Confs)));
|
||||
|
||||
internal static string StatusText(Tx t) => L.T("funds.confirm", Conf(t), t.Confs);
|
||||
|
||||
/// <summary>每帧:更新开着的窗口里的进度条,走完的落地。</summary>
|
||||
internal static void Tick()
|
||||
{
|
||||
if (Active.Count == 0) return;
|
||||
var m = CustomUIManager.Instance;
|
||||
foreach (var t in Active.ToList())
|
||||
{
|
||||
if (Time.unscaledTime - t.Start >= t.Total) { Finish(t); continue; }
|
||||
m?.GetElement(TerminalWindow.Id, "funds_status_" + t.Id)?.SetText(StatusText(t));
|
||||
m?.GetElement(TerminalWindow.Id, "funds_prog_" + t.Id)?.SetProgress(Progress(t));
|
||||
}
|
||||
}
|
||||
|
||||
private static void Finish(Tx t)
|
||||
{
|
||||
if (t.Finished) return;
|
||||
t.Finished = true;
|
||||
Active.Remove(t);
|
||||
Log.Guard("出金落地", () =>
|
||||
{
|
||||
var d = Session.Data;
|
||||
var pb = d.Poinbase;
|
||||
double amt = Math.Min(t.Amount, pb.Avail(t.Asset));
|
||||
double fee = Math.Min(t.Fee, amt);
|
||||
if (fee > 0) Wallet.Transfer(pb, new Wallet(), t.Asset, fee, Session.Price);
|
||||
double net = amt - fee;
|
||||
var own = d.Own(t.To);
|
||||
Wallet.Transfer(pb, own ?? new Wallet(), t.Asset, net, Session.Price);
|
||||
d.Block += 1;
|
||||
d.Chain(d.Address("poinbase"), t.To, t.Asset, net, fee);
|
||||
if (own != null) WalletWindow.RefreshDevice(own, true);
|
||||
else Log.Info($"出金转进没人用的地址 {t.To}:{net} {t.Asset}");
|
||||
Session.Save();
|
||||
TerminalWindow.Refresh(own != null
|
||||
? L.T("funds.done", Fmt.Num(net), t.Asset, WalletWindow.NameOf(own))
|
||||
: L.T("funds.done.void", Fmt.Num(net), t.Asset));
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,417 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using Decentralized.Domain;
|
||||
using UnityEngine;
|
||||
|
||||
namespace Decentralized
|
||||
{
|
||||
/// <summary>
|
||||
/// 显卡鉴定指南:游戏的纸质指南(PaperUI),版式和原版鉴定指南一致——笔记本背景、委员会页眉、居中标题、
|
||||
/// 插图加图注、“价格不变 / -n%”的折价标注、末页的鉴定示例。第一次打开时按当前语言生成并登记,语言变了重新生成。
|
||||
/// 坐标是设计单位(314×402,屏幕上放大 2 倍)。
|
||||
/// </summary>
|
||||
public static class GpuGuide
|
||||
{
|
||||
public const string BookId = "gpu_guide";
|
||||
private const float X = 35f, W = 253f, Top = 80f, Bottom = 368f;
|
||||
private const string Ink = "#221C1A", Good = "#3F7D4B", Bad = "#9E1F1A";
|
||||
|
||||
private static string _locale;
|
||||
private static LoadedMod _mod;
|
||||
|
||||
public static void OnAssetsLoaded(LoadedMod mod)
|
||||
{
|
||||
if (mod?.Manifest?.ID == ModInfo.Id) _mod = mod;
|
||||
}
|
||||
|
||||
/// <summary>原版背景、按钮和页眉图按名字找不到时(纸张素材目录没打包),把内存里同名的原版精灵登记给本 mod。</summary>
|
||||
private static void ProvideMissingPaperSprites()
|
||||
{
|
||||
if (_mod == null) return;
|
||||
foreach (var sprite in Resources.FindObjectsOfTypeAll<Sprite>())
|
||||
{
|
||||
string n = sprite.name;
|
||||
if (n != "notebook_manual" && n != "guide_logo" && !n.StartsWith("paper_buttons")) continue;
|
||||
if (_mod.PaperSprites.ContainsKey(n) || PaperAssets.FindInCatalog(n) != null) continue;
|
||||
_mod.PaperSprites[n] = sprite;
|
||||
}
|
||||
}
|
||||
|
||||
public static void Open(int page = 0)
|
||||
{
|
||||
try
|
||||
{
|
||||
if (_locale != L.Code || !ModHelper.GetPaperBookIds(ModInfo.Id).Contains(BookId)) Register();
|
||||
var ui = ModHelper.OpenPaper(ModInfo.Id, BookId);
|
||||
if (ui == null) { Log.Warn("[GpuGuide] 打不开鉴定指南"); return; }
|
||||
ui.FlipTo(page);
|
||||
RaiseAboveModWindows(ui);
|
||||
}
|
||||
catch (Exception ex) { Log.Error("[GpuGuide] " + ex); }
|
||||
}
|
||||
|
||||
/// <summary>纸质画布在 mod 窗口所在的层下面:从终端里打开时会被盖住,打开期间调到上面,关上时恢复。</summary>
|
||||
private static void RaiseAboveModWindows(PaperUI ui)
|
||||
{
|
||||
var canvas = ui.Root != null ? ui.Root.GetComponentInParent<Canvas>()?.rootCanvas : null;
|
||||
if (canvas == null || canvas.sortingOrder >= 950) return;
|
||||
int old = canvas.sortingOrder;
|
||||
canvas.sortingOrder = 950;
|
||||
void Restore(PaperUI u) { u.Closed -= Restore; if (canvas != null) canvas.sortingOrder = old; }
|
||||
ui.Closed += Restore;
|
||||
}
|
||||
|
||||
// ================= 生成 =================
|
||||
|
||||
private static void Register()
|
||||
{
|
||||
ProvideMissingPaperSprites();
|
||||
ModHelper.RemovePaperBooks(ModInfo.Id);
|
||||
var b = ModHelper.CreatePaper(ModInfo.Id, BookId, "notebook_manual");
|
||||
b.SetSize(628f, 804f);
|
||||
b.SetPosition(-450f, 0f);
|
||||
b.SetChrome();
|
||||
Page1(b); Page2(b); Page3(b); Page4(b); Page5(b); Page6(b); Page7(b); Page8(b); Page9(b);
|
||||
ModHelper.RegisterPaperBook(ModInfo.Id, b.Data);
|
||||
_locale = L.Code;
|
||||
Log.Info($"[GpuGuide] 已登记显卡鉴定指南({b.Data.pages.Count} 页,{_locale})");
|
||||
}
|
||||
|
||||
private static string T(string key, params object[] a) => TuningText.Render(L.T(key, a));
|
||||
|
||||
/// <summary>新的一页:原版的页眉(委员会印章字)和标题。</summary>
|
||||
private static float NewPage(PaperUI b)
|
||||
{
|
||||
b.AddPage(null, "guide_page");
|
||||
b.SetSlot("header", L.T("gg.header"));
|
||||
b.SetSlot("title", L.T("item.guide.name"));
|
||||
b.SetSlot("body", " ");
|
||||
return Top;
|
||||
}
|
||||
|
||||
private static string Img(string name) => ModInfo.Id + ":" + name;
|
||||
|
||||
private static TMPro.TextMeshProUGUI _measurer;
|
||||
|
||||
private static float Measure(string text, string style, float size, float width)
|
||||
{
|
||||
if (_measurer == null)
|
||||
{
|
||||
var go = new GameObject("pd_gpu_guide_measure", typeof(RectTransform));
|
||||
UnityEngine.Object.DontDestroyOnLoad(go);
|
||||
_measurer = go.AddComponent<TMPro.TextMeshProUGUI>();
|
||||
_measurer.enableWordWrapping = true;
|
||||
_measurer.richText = true;
|
||||
}
|
||||
var st = PaperTextStyle.Get(style);
|
||||
var font = st.Font();
|
||||
if (font != null) _measurer.font = font;
|
||||
_measurer.fontSize = size > 0 ? size : st.size;
|
||||
float h = _measurer.GetPreferredValues(text, width, 0).y;
|
||||
return h > 1 ? h + 1.5f : (size > 0 ? size : st.size) * 1.5f * (1 + text.Split('\n').Length);
|
||||
}
|
||||
|
||||
/// <summary>一段文字,返回下一块的 y。</summary>
|
||||
private static float Text(PaperUI b, float y, string text, string style = "body", string color = Ink, string align = "left", float gap = 5f, float x = X, float w = W)
|
||||
{
|
||||
float h = Measure(text, style, 0, w);
|
||||
b.AddText(x, y, w, h, text, style, align: align);
|
||||
b.Last.color = color;
|
||||
if (y + h > Bottom) Log.Warn($"[GpuGuide] 内容超出纸面 overflow:{y + h:0} > {Bottom}({text.Substring(0, Math.Min(18, text.Length))})");
|
||||
return y + h + gap;
|
||||
}
|
||||
|
||||
/// <summary>小节标题(原版的蓝灰色粗体小标题);标题太长折行时按折行后的高度往下推。</summary>
|
||||
private static float Section(PaperUI b, float y, string text)
|
||||
{
|
||||
float h = Mathf.Max(13f, Measure(text, "label", 8f, W));
|
||||
b.AddText(X, y, W, h, text, "label", fontSize: 8f);
|
||||
b.Last.color = "#2E5A78";
|
||||
return y + h + 2f;
|
||||
}
|
||||
|
||||
/// <summary>一张图(底图加叠加层,同一个位置),居中,宽高是显示尺寸;返回图的底边。</summary>
|
||||
private static float Art(PaperUI b, float x, float y, float scale, params string[] layers)
|
||||
{
|
||||
float w = 192f * scale, h = 128f * scale;
|
||||
foreach (var l in layers)
|
||||
{
|
||||
b.AddImage(x, y, w, h, Img(l), "stretch");
|
||||
}
|
||||
return y + h;
|
||||
}
|
||||
|
||||
/// <summary>正面底图:供电口类别(0 = 6 针,1 = 8 针,2 = 双 8 针)与风扇数(1 到 3)各自独立。</summary>
|
||||
private static string Front(string brand, int pin, int count) => $"gpu_big_{brand}_f_p{pin}n{count}";
|
||||
private static string Front(string brand, int tier) => Front(brand, Hardware.PinClass[tier], Hardware.FanCount[tier]);
|
||||
private static int Fans(int tier) => Hardware.FanCount[tier];
|
||||
|
||||
private static void Caption(PaperUI b, float x, float y, float w, string text, string color = null)
|
||||
{
|
||||
b.AddText(x, y, w, 10, text, "caption", align: "center");
|
||||
if (color != null) b.Last.color = color;
|
||||
}
|
||||
|
||||
/// <summary>背面贴纸上的序列号:贴纸在大图 (142, 91) 附近,随图的缩放摆放。</summary>
|
||||
private static void SerialOnSticker(PaperUI b, float ax, float ay, float scale, string serial)
|
||||
{
|
||||
float cx = ax + 142f * scale, cy = ay + 91f * scale;
|
||||
b.AddText(cx - 26f * scale, cy - 4.5f, 52f * scale, 9f, serial, "caption", align: "center", fontSize: 3.2f * scale / 0.78f);
|
||||
b.Last.color = "#1B1B1B";
|
||||
}
|
||||
|
||||
/// <summary>剩余高度能放下的图缩放(图高 128 设计单位):长语言文字多,图自动缩小,不超出纸面。</summary>
|
||||
private static float FitScale(float usedHeight, int count, float max, float min = 0.3f)
|
||||
{
|
||||
float avail = Bottom - Top - usedHeight;
|
||||
return Mathf.Clamp(avail / (128f * count), min, max);
|
||||
}
|
||||
|
||||
private static string SampleSerial(string model, string chip = null, int kind = 0)
|
||||
{
|
||||
var u = new Unit { Model = model, FakeOf = chip, Health = 100, Look = new CardLook { Seed = 31337, Serial = kind } };
|
||||
return CardLabels.SerialText(u);
|
||||
}
|
||||
|
||||
// ---- 1 概述 ----
|
||||
private static void Page1(PaperUI b)
|
||||
{
|
||||
float y = NewPage(b);
|
||||
string body = L.T("gg.p1.body"), makers = L.T("gg.p1.makers"), note = T("gg.p1.note");
|
||||
float used = Measure(body, "body", 0, W) + Measure(makers, "body", 0, W) + Measure(note, "body", 7f, W) + 6f + 14f + 8f + 14f;
|
||||
float scale = FitScale(used, 1, 0.9f);
|
||||
y = Text(b, y, body, gap: 6f);
|
||||
float x = X + (W - 192f * scale) / 2;
|
||||
float bottom = Art(b, x, y, scale, Front("probidia", 1));
|
||||
Caption(b, X, bottom + 1, W, L.T("gg.p1.cap"));
|
||||
y = bottom + 14f;
|
||||
y = Text(b, y, makers, gap: 8f);
|
||||
Text(b, y, note, "body", Good);
|
||||
b.Last.fontSize = 7f;
|
||||
}
|
||||
|
||||
// ---- 2 显卡型号 ----
|
||||
private static void Page2(PaperUI b)
|
||||
{
|
||||
float y = NewPage(b);
|
||||
y = Section(b, y, L.T("gg.p2.h"));
|
||||
y = Text(b, y, L.T("gg.p2.body"), gap: 6f);
|
||||
float cw = W / 2;
|
||||
for (int row = 0; row < 2; row++)
|
||||
{
|
||||
float rowBottom = y;
|
||||
for (int col = 0; col < 2; col++)
|
||||
{
|
||||
int tier = row * 2 + col;
|
||||
float ax = X + col * cw + (cw - 120f) / 2;
|
||||
float bottom = Art(b, ax, y, 0.625f, Front("probidia", tier));
|
||||
Caption(b, X + col * cw, bottom, cw, L.T("gg.tier." + tier));
|
||||
rowBottom = bottom + 12f;
|
||||
}
|
||||
y = rowBottom + 4f;
|
||||
}
|
||||
}
|
||||
|
||||
// ---- 3 风扇数 ----
|
||||
private static void Page3(PaperUI b)
|
||||
{
|
||||
float y = NewPage(b);
|
||||
y = Section(b, y, L.T("gg.count.h"));
|
||||
string cb = L.T("gg.count.body");
|
||||
float cs = FitScale(15f + Measure(cb, "body", 0, W) + 6f + 3 * 15f, 3, 0.5f, 0.3f);
|
||||
y = Text(b, y, cb, gap: 6f);
|
||||
for (int n = 1; n <= 3; n++)
|
||||
{
|
||||
float bottom = Art(b, X + (W - 192f * cs) / 2, y, cs, Front("probidia", 1, n));
|
||||
Caption(b, X, bottom, W, L.T("lbl.count." + n));
|
||||
y = bottom + 15f;
|
||||
}
|
||||
}
|
||||
|
||||
// ---- 4 供电口 ----
|
||||
private static void Page4(PaperUI b)
|
||||
{
|
||||
float y = NewPage(b);
|
||||
y = Section(b, y, L.T("gg.pin.h"));
|
||||
string pbd = L.T("gg.pin.body");
|
||||
float ps = FitScale(15f + Measure(pbd, "body", 0, W) + 6f + 3 * 15f, 3, 0.5f, 0.3f);
|
||||
y = Text(b, y, pbd, gap: 6f);
|
||||
for (int p = 0; p < 3; p++)
|
||||
{
|
||||
float bottom = Art(b, X + (W - 192f * ps) / 2, y, ps, Front("probidia", p, 2));
|
||||
Caption(b, X, bottom, W, L.T("lbl.pin." + p));
|
||||
y = bottom + 15f;
|
||||
}
|
||||
}
|
||||
|
||||
// ---- 5 序列号 ----
|
||||
private static void Page5(PaperUI b)
|
||||
{
|
||||
float y = NewPage(b);
|
||||
y = Section(b, y, L.T("gg.serial.h"));
|
||||
string body = L.T("gg.serial.body"), pb = L.T("gg.serial.pb"), md = L.T("gg.serial.md"), rule = L.T("gg.serial.rule");
|
||||
float used = 15f + Measure(body, "body", 0, W) + Measure(pb, "body", 0, W) + Measure(md, "body", 0, W) + Measure(rule, "body", 0, W) + 6f + 14f + 4f + 8f;
|
||||
float scale = FitScale(used, 1, 0.78f);
|
||||
y = Text(b, y, body, gap: 6f);
|
||||
float ax = X + (W - 192f * scale) / 2;
|
||||
float bottom = Art(b, ax, y, scale, "gpu_big_probidia_b", "gpu_big_ov_print_normal_rtx80");
|
||||
SerialOnSticker(b, ax, y, scale, SampleSerial("RTX80"));
|
||||
Caption(b, X, bottom + 1, W, L.T("gg.serial.cap"));
|
||||
y = bottom + 14f;
|
||||
y = Text(b, y, pb, gap: 4f);
|
||||
y = Text(b, y, md, gap: 8f);
|
||||
Text(b, y, rule, "body");
|
||||
}
|
||||
|
||||
// ---- 6 背面丝印 ----
|
||||
private static void Page6(PaperUI b)
|
||||
{
|
||||
float y = NewPage(b);
|
||||
y = Section(b, y, L.T("gg.print.h"));
|
||||
string note = L.T("gg.print.note");
|
||||
string[] kinds = { "normal", "stamp", "skew" };
|
||||
float scale = FitScale(15f + Measure(note, "body", 0, W) + 3 * 14f, 3, 0.5f, 0.3f);
|
||||
for (int s = 0; s < 3; s++)
|
||||
{
|
||||
string model = s == 1 ? "rtx60" : "rtx80";
|
||||
float ax = X + (W - 192f * scale) / 2;
|
||||
float bottom = Art(b, ax, y, scale, "gpu_big_probidia_b", $"gpu_big_ov_print_{kinds[s]}_{model}");
|
||||
SerialOnSticker(b, ax, y, scale, SampleSerial("RTX80"));
|
||||
Caption(b, X, bottom, W, L.T("gg.print." + s), s == 0 ? null : Bad);
|
||||
y = bottom + 14f;
|
||||
}
|
||||
Text(b, y, note, "body");
|
||||
}
|
||||
|
||||
// ---- 7 叶片与金手指 ----
|
||||
private static void Page7(PaperUI b)
|
||||
{
|
||||
float y = NewPage(b);
|
||||
y = Section(b, y, L.T("gg.fan.h"));
|
||||
float cw = W / 3;
|
||||
float bottom = y;
|
||||
for (int s = 0; s < 3; s++)
|
||||
{
|
||||
var layers = new List<string> { Front("probidia", 1) };
|
||||
if (s == 1) layers.Add("gpu_big_ov_fan_dust2_" + Fans(1));
|
||||
if (s == 2) { layers.Add("gpu_big_ov_fan_dust1_" + Fans(1)); layers.Add("gpu_big_ov_fan_chip_" + Fans(1)); }
|
||||
float bx = Art(b, X + s * cw + (cw - 78f) / 2, y, 0.4f, layers.ToArray());
|
||||
Caption(b, X + s * cw, bx, cw, T("gg.fan." + s), s == 0 ? null : Bad);
|
||||
bottom = bx + 24f;
|
||||
}
|
||||
y = bottom + 10f;
|
||||
y = Section(b, y, L.T("gg.fin.h"));
|
||||
for (int s = 0; s < 3; s++)
|
||||
{
|
||||
var layers = new List<string> { Front("probidia", 1) };
|
||||
if (s == 1) layers.Add("gpu_big_ov_fin_dim");
|
||||
if (s == 2) layers.Add("gpu_big_ov_fin_oxide");
|
||||
float bx = Art(b, X + s * cw + (cw - 78f) / 2, y, 0.4f, layers.ToArray());
|
||||
Caption(b, X + s * cw, bx, cw, T("gg.fin." + s), s == 0 ? null : Bad);
|
||||
bottom = bx + 24f;
|
||||
}
|
||||
Text(b, bottom + 6f, L.T("gg.wear.note"), "body");
|
||||
}
|
||||
|
||||
// ---- 8 挡板与封条 ----
|
||||
private static void Page8(PaperUI b)
|
||||
{
|
||||
float y = NewPage(b);
|
||||
y = Section(b, y, L.T("gg.brk.h"));
|
||||
float cw = W / 2;
|
||||
float bottom = y;
|
||||
for (int s = 0; s < 2; s++)
|
||||
{
|
||||
var layers = new List<string> { Front("probidia", 1) };
|
||||
if (s == 1) layers.Add("gpu_big_ov_brk_scratch");
|
||||
float bx = Art(b, X + s * cw + (cw - 120f) / 2, y, 0.625f, layers.ToArray());
|
||||
Caption(b, X + s * cw, bx, cw, T("gg.brk." + s), s == 0 ? null : Bad);
|
||||
bottom = bx + 12f;
|
||||
}
|
||||
y = bottom + 10f;
|
||||
y = Section(b, y, L.T("gg.seal.h"));
|
||||
bottom = y;
|
||||
for (int s = 0; s < 2; s++)
|
||||
{
|
||||
var layers = new List<string> { "gpu_big_probidia_b", "gpu_big_ov_print_normal_rtx70" };
|
||||
if (s == 1) layers.Add("gpu_big_ov_seal_missing");
|
||||
float ax = X + s * cw + (cw - 120f) / 2;
|
||||
float bx = Art(b, ax, y, 0.625f, layers.ToArray());
|
||||
SerialOnSticker(b, ax, y, 0.625f, SampleSerial("RTX70"));
|
||||
Caption(b, X + s * cw, bx, cw, T(s == 0 ? "gg.seal.0" : "gg.seal.2"), s == 0 ? null : Bad);
|
||||
bottom = bx + 12f;
|
||||
}
|
||||
}
|
||||
|
||||
// ---- 9 指出 ----
|
||||
private static void Page9(PaperUI b)
|
||||
{
|
||||
float y = NewPage(b);
|
||||
y = Section(b, y, L.T("gg.point.h"));
|
||||
Text(b, y, T("gg.point.body"), "body");
|
||||
foreach (var e in Examples) ExamplePage(b, e);
|
||||
}
|
||||
|
||||
// ---- 9 起:鉴定示例 ----
|
||||
private sealed class Ex { public string Title, Label, Chip; public int Health, Fan, Fingers, Bracket, Seal, CountBad, PinBad, SerialBad; }
|
||||
|
||||
private static readonly Ex[] Examples =
|
||||
{
|
||||
new Ex { Title = "gg.ex.h", Label = "RTX80", Health = 60, Fan = 2, Fingers = 1, Seal = 2 },
|
||||
new Ex { Title = "gg.ex.h3", Label = "RX800", Health = 35, Fan = 2, Fingers = 2, Bracket = 1, Seal = 2 },
|
||||
new Ex { Title = "gg.ex.h2", Label = "RTX90", Chip = "RTX60", Health = 90, Fan = 1, CountBad = 1, SerialBad = 2 },
|
||||
new Ex { Title = "gg.ex.h4", Label = "RTX70", Health = 85, Fan = 1 },
|
||||
new Ex { Title = "gg.ex.h5", Label = "RX70", Health = 100 },
|
||||
};
|
||||
|
||||
|
||||
private static string Brand(string model) => Hardware.Specs[model].Brand.ToString();
|
||||
|
||||
private static void ExamplePage(PaperUI b, Ex e)
|
||||
{
|
||||
float y = NewPage(b);
|
||||
y = Section(b, y, L.T(e.Title));
|
||||
string real = e.Chip ?? e.Label;
|
||||
var u = new Unit { Model = e.Label, FakeOf = e.Chip, Health = e.Health, Look = new CardLook { Seed = 31337, Fan = e.Fan, Fingers = e.Fingers, Bracket = e.Bracket, Sticker = e.Seal, CountBad = e.CountBad, PinBad = e.PinBad, Serial = e.SerialBad } };
|
||||
long baseV = CardValue.Of(real, e.Health);
|
||||
string brandKey = Hardware.Specs[real].Brand == "PMD" ? "pmd" : "probidia";
|
||||
var layers = new List<string> { Front(brandKey, u.ObservedPin, u.ObservedCount) };
|
||||
int fans = u.ObservedCount;
|
||||
if (e.Fan == 1) layers.Add("gpu_big_ov_fan_dust2_" + fans);
|
||||
if (e.Fan == 2) { layers.Add("gpu_big_ov_fan_dust1_" + fans); layers.Add("gpu_big_ov_fan_chip_" + fans); }
|
||||
if (e.Fingers == 1) layers.Add("gpu_big_ov_fin_dim");
|
||||
if (e.Fingers == 2) layers.Add("gpu_big_ov_fin_oxide");
|
||||
if (e.Bracket == 1) layers.Add("gpu_big_ov_brk_scratch");
|
||||
float bottom = Art(b, X + (W - 140f) / 2, y, 0.73f, layers.ToArray());
|
||||
y = bottom + 6f;
|
||||
string name = Hardware.Specs[e.Label].Brand + " " + Items.DisplayModel(e.Label);
|
||||
y = Text(b, y, L.T("gg.ex.card", name, e.Health), "body", align: "center", gap: 3f);
|
||||
y = Text(b, y, L.T("gg.ex.serial", CardLabels.SerialText(u)), "caption", Ink, "center", 8f);
|
||||
const float lx = X + 20f, lw = W - 40f;
|
||||
if (e.Chip != null)
|
||||
{
|
||||
y = Text(b, y, L.T("gg.ex.fake", name, Hardware.Specs[e.Chip].Brand + " " + Items.DisplayModel(e.Chip)), "caption", Bad, "center", 6f);
|
||||
y = Text(b, y, L.T("gg.ex.claimed", CardValue.Of(e.Label, e.Health)), "caption", Ink, "right", 3f, lx, lw);
|
||||
}
|
||||
y = Text(b, y, L.T("gg.ex.base", baseV), "caption", Ink, "right", 3f, lx, lw);
|
||||
int n = 0; long discSum = 0;
|
||||
long Disc(double p) { n++; long d = (long)Math.Round(baseV * p); discSum += d; return d; }
|
||||
if (e.Fan == 1) y = Text(b, y, L.T("gg.ex.fan1", Disc(Tuning.CardFanDust)), "caption", Bad, "right", 3f, lx, lw);
|
||||
if (e.Fan == 2) y = Text(b, y, L.T("gg.ex.fan", Disc(Tuning.CardFanChipped)), "caption", Bad, "right", 3f, lx, lw);
|
||||
if (e.Fingers == 1) y = Text(b, y, L.T("gg.ex.fin", Disc(Tuning.CardFingersDark)), "caption", Bad, "right", 3f, lx, lw);
|
||||
if (e.Fingers == 2) y = Text(b, y, L.T("gg.ex.fin2", Disc(Tuning.CardFingersOxidized)), "caption", Bad, "right", 3f, lx, lw);
|
||||
if (e.Bracket == 1) y = Text(b, y, L.T("gg.ex.brk", Disc(Tuning.CardBracketScratch)), "caption", Bad, "right", 3f, lx, lw);
|
||||
if (e.Seal == 2) y = Text(b, y, L.T("gg.ex.seal", Disc(Tuning.CardSealMissing)), "caption", Bad, "right", 3f, lx, lw);
|
||||
if (n == 0) y = Text(b, y, L.T("gg.ex.nodisc"), "caption", Good, "right", 3f, lx, lw);
|
||||
y += 3f;
|
||||
b.AddLine(lx, y, lx + lw, y, 1f, "#6A6458");
|
||||
y += 6f;
|
||||
// 外观写死(种子 0)才不会被健康度重算覆盖,价值按它算;序列号要种子,用上面带种子的那个
|
||||
long total = baseV - discSum; // 页面上各项相加,和游戏的价值函数差不过 1(四舍五入)
|
||||
y = Text(b, y, L.T("gg.ex.total", total), "label", Ink, "right", 8f, lx, lw);
|
||||
if (e.Chip != null) y = Text(b, y, L.T("gg.ex.gap", CardValue.Of(e.Label, e.Health) - total), "caption", Bad, "right", 8f, lx, lw);
|
||||
Text(b, y, L.T("gg.ex.note"), "caption", Ink, "center");
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,320 @@
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using Decentralized.Domain;
|
||||
using TMPro;
|
||||
using UnityEngine;
|
||||
using UnityEngine.UI;
|
||||
|
||||
namespace Decentralized
|
||||
{
|
||||
/// <summary>
|
||||
/// 放大镜检视显卡:和香烟一样把物品放大摆在检视台上,正反面各一张,下面是标签栏。
|
||||
/// 标签栏每行一个标签(型号、风扇、金手指、挡板、丝印、贴纸):左边是卖家的说法,右边的按钮"指出"——
|
||||
/// 说法属实就没事,隐瞒了问题价格回到真实情况,指错了掉信誉。归自己的卡,有标签机时按钮改成"改",随便改说法。
|
||||
/// 游戏没有给 mod 开放检视界面,这里不打补丁,只在检视台(InspectionUIManager.panel)下面挂一个自己的界面,
|
||||
/// 用一个常驻的 MonoBehaviour 每帧看一眼是否正在检视显卡。
|
||||
/// </summary>
|
||||
public sealed class GpuInspectView : MonoBehaviour
|
||||
{
|
||||
private const float RowH = 26f, CardScale = 3f, PanelTop = -112f, DetailH = 26f, GroupGap = 7f;
|
||||
private static readonly int RowCount = CardLabels.Rows.Length;
|
||||
private TextMeshProUGUI priceText;
|
||||
private static GpuInspectView instance;
|
||||
private RectTransform root, cardRoot;
|
||||
private Button flip;
|
||||
private TextMeshProUGUI flipText;
|
||||
private GameItem shown;
|
||||
private string shownSig;
|
||||
private bool hidGlass;
|
||||
private Transform buttonTemplate;
|
||||
private TMP_FontAsset font;
|
||||
private readonly TextMeshProUGUI[] rowName = new TextMeshProUGUI[16], rowText = new TextMeshProUGUI[16];
|
||||
private readonly Button[] rowButton = new Button[16];
|
||||
private readonly TextMeshProUGUI[] rowButtonText = new TextMeshProUGUI[16];
|
||||
private TextMeshProUGUI serialText;
|
||||
|
||||
public static void Ensure()
|
||||
{
|
||||
if (instance != null) return;
|
||||
var go = new GameObject("pd_gpu_inspect_view");
|
||||
DontDestroyOnLoad(go);
|
||||
instance = go.AddComponent<GpuInspectView>();
|
||||
}
|
||||
|
||||
public static void Remove()
|
||||
{
|
||||
if (instance != null) Destroy(instance.gameObject);
|
||||
instance = null;
|
||||
}
|
||||
|
||||
private void Update()
|
||||
{
|
||||
var m = InspectionUIManager.Instance;
|
||||
var item = m != null && m.panel != null && m.panel.activeSelf ? m.currentInspectingItem : null;
|
||||
if (item == null || !Items.IsGpu(item))
|
||||
{
|
||||
if (root != null && root.gameObject.activeSelf) root.gameObject.SetActive(false);
|
||||
shown = null;
|
||||
if (hidGlass && m != null && m.magnifyingGlass != null) { m.magnifyingGlass.SetActive(true); hidGlass = false; }
|
||||
return;
|
||||
}
|
||||
Log.Guard("显卡检视大图", () =>
|
||||
{
|
||||
if (root == null) Build(m);
|
||||
if (!root.gameObject.activeSelf) root.gameObject.SetActive(true);
|
||||
// 检视台自带的放大镜图标会压在大图下面,显卡用不着
|
||||
if (m.magnifyingGlass != null && m.magnifyingGlass.activeSelf) { m.magnifyingGlass.SetActive(false); hidGlass = true; }
|
||||
var keys = new List<string>();
|
||||
string sig = Items.LookKeys(item, keys) + "|" + string.Join(",", keys) + "|" + item.unitValue + "|" + Items.Exposed(item) + "|" + (Items.GetClaim(item)?.Encode() ?? "") + "|" + GeneralHelper.IsItemOwned(item) + "|" + HasLabeler();
|
||||
if (item != shown || sig != shownSig)
|
||||
{
|
||||
shown = item;
|
||||
shownSig = sig;
|
||||
Redraw(item);
|
||||
UpdateRows(item);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
/// <summary>检视台上的叠加层:每个标签的每个取值对应一种细节,一一对应。</summary>
|
||||
public static List<string> BigOverlays(GameItem item)
|
||||
{
|
||||
var o = new List<string>();
|
||||
var u = Items.ToUnit(item);
|
||||
if (u.Dead) return o;
|
||||
var l = u.Appearance;
|
||||
string P = "gpu_big_ov_";
|
||||
if (!Items.IsBack(item))
|
||||
{
|
||||
int n = Items.FansOf(u);
|
||||
if (l.Fan == 1) o.Add(P + "fan_dust2_" + n);
|
||||
if (l.Fan == 2) { o.Add(P + "fan_dust1_" + n); o.Add(P + "fan_chip_" + n); }
|
||||
if (l.Fingers == 1) o.Add(P + "fin_dim");
|
||||
if (l.Fingers == 2) o.Add(P + "fin_oxide");
|
||||
if (l.Bracket == 1) o.Add(P + "brk_scratch");
|
||||
}
|
||||
else
|
||||
{
|
||||
string model = (l.Print == 1 && u.FakeOf != null ? u.FakeOf : u.Model).ToLowerInvariant();
|
||||
o.Add(P + "print_" + (l.Print == 2 ? "skew_" : l.Print == 1 ? "stamp_" : "normal_") + model);
|
||||
if (l.Sticker == 2) o.Add(P + "seal_missing");
|
||||
}
|
||||
return o;
|
||||
}
|
||||
|
||||
private static bool HasLabeler() => EmporiumEntry.Instance != null && EmporiumEntry.Instance.GetAllOwnedItemsByTag("LABELER_TAG").Count > 0;
|
||||
|
||||
private static void MakeRect(Transform parent, string name, Vector2 pos, Vector2 size, Color color)
|
||||
{
|
||||
var go = new GameObject(name, typeof(RectTransform), typeof(Image));
|
||||
var rt = go.GetComponent<RectTransform>();
|
||||
rt.SetParent(parent, false);
|
||||
rt.sizeDelta = size;
|
||||
rt.localPosition = pos;
|
||||
var img = go.GetComponent<Image>();
|
||||
img.color = color;
|
||||
img.raycastTarget = false;
|
||||
}
|
||||
|
||||
private TextMeshProUGUI MakeText(Transform parent, string name, Vector2 pos, Vector2 size, TextAlignmentOptions align, float fontSize)
|
||||
{
|
||||
var go = new GameObject(name, typeof(RectTransform), typeof(TextMeshProUGUI));
|
||||
var rt = go.GetComponent<RectTransform>();
|
||||
rt.SetParent(parent, false);
|
||||
rt.sizeDelta = size;
|
||||
rt.localPosition = pos;
|
||||
var t = go.GetComponent<TextMeshProUGUI>();
|
||||
if (font != null) t.font = font;
|
||||
t.fontSize = fontSize;
|
||||
t.alignment = align;
|
||||
t.enableWordWrapping = false;
|
||||
t.overflowMode = TextOverflowModes.Ellipsis;
|
||||
t.raycastTarget = false;
|
||||
return t;
|
||||
}
|
||||
|
||||
private Button MakeButton(Transform parent, string name, Vector2 pos, Vector2 size, out TextMeshProUGUI label)
|
||||
{
|
||||
var go = Instantiate(buttonTemplate.gameObject, parent, false);
|
||||
go.name = name;
|
||||
var rt = (RectTransform)go.transform;
|
||||
rt.sizeDelta = size;
|
||||
rt.localPosition = pos;
|
||||
var b = go.GetComponent<Button>();
|
||||
b.onClick = new Button.ButtonClickedEvent();
|
||||
label = go.GetComponentInChildren<TextMeshProUGUI>();
|
||||
label.enableAutoSizing = true; label.fontSizeMin = 12; label.fontSizeMax = 24;
|
||||
// 去掉复制来的按钮上驱动文字的本地化组件,文字由这里设置
|
||||
foreach (var mb in go.GetComponentsInChildren<MonoBehaviour>(true))
|
||||
{
|
||||
string n = mb.GetType().Name;
|
||||
if (mb is Button || mb is Image || mb is TextMeshProUGUI) continue;
|
||||
if (n.Contains("Local") || n.Contains("Appraisal") || n.Contains("Send")) Destroy(mb);
|
||||
}
|
||||
return b;
|
||||
}
|
||||
|
||||
private void Build(InspectionUIManager m)
|
||||
{
|
||||
root = new GameObject("_PdGpuInspection", typeof(RectTransform)).GetComponent<RectTransform>();
|
||||
root.SetParent(m.panel.transform, false);
|
||||
root.sizeDelta = new Vector2(1920, 1080);
|
||||
root.localPosition = Vector3.zero;
|
||||
cardRoot = new GameObject("Card", typeof(RectTransform)).GetComponent<RectTransform>();
|
||||
cardRoot.SetParent(root, false);
|
||||
cardRoot.localPosition = new Vector3(0, 85, 0);
|
||||
buttonTemplate = m.appraisalPanel.transform.Find("buttonSend");
|
||||
// 贴纸上的序列号:随卡变化,运行时用文字写在贴纸的空白处
|
||||
serialText = MakeText(root, "Serial", Vector2.zero, new Vector2(48 * CardScale, 8 * CardScale), TextAlignmentOptions.Center, 20);
|
||||
serialText.color = new Color(0.1f, 0.1f, 0.13f);
|
||||
serialText.fontStyle = FontStyles.Bold;
|
||||
serialText.overflowMode = TextOverflowModes.Overflow;
|
||||
serialText.rectTransform.sizeDelta = new Vector2(48 * CardScale, 14 * CardScale);
|
||||
if (buttonTemplate == null) return;
|
||||
font = buttonTemplate.GetComponentInChildren<TextMeshProUGUI>()?.font;
|
||||
if (font != null) serialText.font = font;
|
||||
// 标签区:深色底加浅色边框,和上面的大图分开。三组:四项真伪依据、型号、四项成色,最下面一行是标签价
|
||||
float panelH = RowCount * RowH + 10f + DetailH + GroupGap * 2, panelY = PanelTop - panelH / 2;
|
||||
MakeRect(root, "LabelFrame", new Vector2(0, panelY), new Vector2(648, panelH + 8), new Color(0.78f, 0.68f, 0.45f, 1f));
|
||||
MakeRect(root, "LabelBack", new Vector2(0, panelY), new Vector2(640, panelH), new Color(0.10f, 0.11f, 0.14f, 0.96f));
|
||||
MakeRect(root, "LabelDivider1", new Vector2(0, GroupTop(CardLabels.AuthRows) + GroupGap / 2 + 1), new Vector2(620, 2), new Color(0.78f, 0.68f, 0.45f, 0.8f));
|
||||
MakeRect(root, "LabelDivider2", new Vector2(0, GroupTop(CardLabels.AuthRows + 1) + GroupGap / 2 + 1), new Vector2(620, 2), new Color(0.78f, 0.68f, 0.45f, 0.5f));
|
||||
MakeRect(root, "LabelDivider3", new Vector2(0, PanelTop - 5 - RowH * RowCount - GroupGap * 2 - 1), new Vector2(620, 2), new Color(0.78f, 0.68f, 0.45f, 0.8f));
|
||||
priceText = MakeText(root, "LabelPrice", new Vector2(165, PanelTop - 5 - RowH * RowCount - GroupGap * 2 - DetailH / 2 - 2), new Vector2(300, DetailH), TextAlignmentOptions.Right, 21);
|
||||
priceText.color = new Color(1f, 0.85f, 0.45f);
|
||||
PledgerSkin.Fit(priceText);
|
||||
flip = MakeButton(root, "Flip", new Vector2(0, PanelTop - panelH - 24), new Vector2(200, 30), out flipText);
|
||||
flip.onClick.AddListener(() => { if (shown != null) Items.Flip(shown); });
|
||||
for (int i = 0; i < RowCount; i++)
|
||||
{
|
||||
int row = CardLabels.Rows[i];
|
||||
float y = GroupTop(i) - RowH / 2;
|
||||
rowName[i] = MakeText(root, "RowName" + i, new Vector2(-232, y), new Vector2(156, RowH), TextAlignmentOptions.Left, 20);
|
||||
rowText[i] = MakeText(root, "RowText" + i, new Vector2(24, y), new Vector2(300, RowH), TextAlignmentOptions.Left, 20);
|
||||
rowButton[i] = MakeButton(root, "RowButton" + i, new Vector2(245, y), new Vector2(110, RowH - 3), out rowButtonText[i]);
|
||||
rowButton[i].onClick.AddListener(() => Log.Guard("标签栏", () => OnRowButton(row)));
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>第 i 行的上沿(三组之间各留一道间隔)。</summary>
|
||||
private static float GroupTop(int i) => PanelTop - 5 - RowH * i - (i >= CardLabels.AuthRows ? GroupGap : 0f) - (i >= CardLabels.AuthRows + 1 ? GroupGap : 0f);
|
||||
|
||||
private static string RowKey(int row) => row == CardLabels.RowSpec ? "spec" : row == CardLabels.RowCount ? "count" : row == CardLabels.RowPin ? "pin" : row == CardLabels.RowFan ? "fan" : row == CardLabels.RowFingers ? "fingers"
|
||||
: row == CardLabels.RowBracket ? "bracket" : row == CardLabels.RowPrint ? "print" : row == CardLabels.RowSerial ? "serial" : "seal";
|
||||
|
||||
private static string ValueText(int row, int value) => row == CardLabels.RowSpec ? "" : L.T("lbl." + RowKey(row) + "." + (row == CardLabels.RowSeal && value == 1 ? 0 : value));
|
||||
|
||||
private static string RowName(int row) => L.T("lbl.row." + RowKey(row));
|
||||
|
||||
/// <summary>现场有没有卖家 / 鉴定客户在:决定"指出"按钮是否出现。</summary>
|
||||
private static bool CanPoint(GameItem item)
|
||||
{
|
||||
var client = PlayerStore.Instance.currentClientInstance?.GetClientBlueprint();
|
||||
if (client == null || GeneralHelper.IsItemOwned(item)) return false;
|
||||
if (client.clientIntent == StoreClient.ClientIntent.APPRAISAL_SERVICE) return true;
|
||||
return client.clientIntent == StoreClient.ClientIntent.SELL && !InspectionUIManager.IsConfrontLocked();
|
||||
}
|
||||
|
||||
private void UpdateRows(GameItem item)
|
||||
{
|
||||
if (rowName[0] == null) return;
|
||||
var u = Items.ToUnit(item);
|
||||
var real = Claim.Truth(u);
|
||||
var claim = Items.GetClaim(item);
|
||||
int exposed = Items.Exposed(item);
|
||||
bool owned = GeneralHelper.IsItemOwned(item);
|
||||
bool canPoint = CanPoint(item), canEdit = owned && HasLabeler();
|
||||
for (int i = 0; i < RowCount; i++)
|
||||
{
|
||||
int row = CardLabels.Rows[i];
|
||||
rowName[i].text = RowName(row);
|
||||
rowName[i].color = i < CardLabels.AuthRows ? new Color(1f, 0.85f, 0.45f) : new Color(0.6f, 0.85f, 1f); // 真伪行金黄,成色行浅蓝
|
||||
rowName[i].fontSize = 20; PledgerSkin.Fit(rowName[i]); PledgerSkin.Fit(rowText[i]);
|
||||
string text;
|
||||
Color color = new Color(0.96f, 0.98f, 1f);
|
||||
string Show(Claim c) => row == CardLabels.RowSpec ? DisplayModel(c.Model) : ValueText(row, c.Get(row));
|
||||
if (claim == null) text = Show(real);
|
||||
else if ((exposed & row) != 0)
|
||||
{
|
||||
text = Show(real);
|
||||
bool lied = row == CardLabels.RowSpec ? claim.Value.Model != real.Model : claim.Value.Get(row) != real.Get(row);
|
||||
if (lied) color = new Color(1f, 0.45f, 0.4f); // 卖家的说法只在机制里起作用,面板上不写
|
||||
else color = new Color(0.5f, 1f, 0.55f);
|
||||
}
|
||||
else text = Show(claim.Value);
|
||||
rowText[i].text = text;
|
||||
rowText[i].color = color;
|
||||
bool editable = row == CardLabels.RowSpec || !CardLabels.IsAuth(row);
|
||||
bool hasButton = row == CardLabels.RowSpec || !CardLabels.IsAuth(row);
|
||||
rowButton[i].gameObject.SetActive(hasButton && (canEdit ? editable : canPoint && (exposed & row) == 0));
|
||||
rowButtonText[i].text = L.T(canEdit ? "lbl.edit" : row == CardLabels.RowSpec ? "lbl.point.model" : "lbl.point");
|
||||
}
|
||||
if (priceText != null) priceText.text = L.T("lbl.price", item.unitValue);
|
||||
if (flipText != null) flipText.text = L.T(Items.IsBack(item) ? "inspect.flip.front" : "inspect.flip.back");
|
||||
// 贴纸上的序列号:只在背面显示
|
||||
if (serialText != null)
|
||||
{
|
||||
serialText.gameObject.SetActive(Items.IsBack(item) && !u.Dead);
|
||||
serialText.text = CardLabels.SerialText(u);
|
||||
// 贴纸空白处中心在大图 (142, 91):卡片坐标以图中心为原点,y 向上
|
||||
serialText.rectTransform.localPosition = new Vector3((142 - 96) * CardScale, 85 + (64 - 91) * CardScale, 0);
|
||||
}
|
||||
}
|
||||
|
||||
private static string DisplayModel(string model) => Items.DisplayModel(model);
|
||||
|
||||
private void OnRowButton(int row)
|
||||
{
|
||||
if (shown == null) return;
|
||||
var item = shown;
|
||||
if (GeneralHelper.IsItemOwned(item))
|
||||
{
|
||||
// 标签机:改说法,每按一次换下一个取值(型号是在八个型号里轮换)
|
||||
var u = Items.ToUnit(item);
|
||||
var cur = Items.GetClaim(item) ?? Claim.Truth(u);
|
||||
if (row == CardLabels.RowSpec)
|
||||
{
|
||||
var models = Hardware.Specs.Values.Where(s => !s.Asic && !s.Scrap).Select(s => s.Model).ToList();
|
||||
Items.EditClaim(item, row, 0, models[(models.IndexOf(cur.Model) + 1) % models.Count]);
|
||||
}
|
||||
else Items.EditClaim(item, row, row == CardLabels.RowSeal ? (cur.Get(row) == 0 ? 2 : 0) : row == CardLabels.RowBracket ? (cur.Get(row) + 1) % 2 : (cur.Get(row) + 1) % 3);
|
||||
EmporiumAudioPlayer.Instance?.audioLabeler?.Play();
|
||||
return;
|
||||
}
|
||||
int kind = Items.Point(item, row);
|
||||
Log.Info($"指出 {row},结果 {kind},报价 {item.unitValue}");
|
||||
if (kind == 0)
|
||||
{
|
||||
InspectionUIManager.Instance.OnConfrontFailed();
|
||||
DialogUIManager.Instance.StartDialogue(new Dialogue().SetText("CLIENT", L.T("point.none." + Random.Range(1, 3))));
|
||||
}
|
||||
else
|
||||
{
|
||||
InspectionUIManager.Instance.OnConfrontSuccess();
|
||||
DialogUIManager.Instance.StartDialogue(new Dialogue().SetText("CLIENT", L.T(kind == 2 ? "point.fake." + Random.Range(1, 3) : "point.worn." + Random.Range(1, 3))));
|
||||
}
|
||||
}
|
||||
|
||||
private void Redraw(GameItem item)
|
||||
{
|
||||
foreach (Transform c in cardRoot) Destroy(c.gameObject);
|
||||
var keys = new List<string>();
|
||||
string baseKey = Items.LookKeys(item, keys); // 小图键名只用来取底图(品牌与正反面)
|
||||
var layers = new List<string> { "gpu_big_" + baseKey.Substring("gpu_".Length) };
|
||||
layers.AddRange(BigOverlays(item));
|
||||
foreach (var k in layers)
|
||||
{
|
||||
var sprite = Items.ModSprite(k);
|
||||
if (sprite == null) continue;
|
||||
var go = new GameObject(k, typeof(RectTransform), typeof(Image));
|
||||
var rt = go.GetComponent<RectTransform>();
|
||||
rt.SetParent(cardRoot, false);
|
||||
rt.sizeDelta = new Vector2(sprite.rect.width, sprite.rect.height);
|
||||
rt.localScale = Vector3.one * CardScale;
|
||||
var img = go.GetComponent<Image>();
|
||||
img.sprite = sprite;
|
||||
img.raycastTarget = false;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,100 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using UnityEngine;
|
||||
using UnityEngine.UI;
|
||||
using Decentralized.Domain;
|
||||
|
||||
namespace Decentralized
|
||||
{
|
||||
/// <summary>Web3 手册阅读窗口:左边章节列表,右边章节全文。章节在本地化文本里用 § 分隔,章节名取第一个冒号或括号之前。</summary>
|
||||
public static class HandbookWindow
|
||||
{
|
||||
public const string Id = "pd_handbook";
|
||||
private const float WinW = 828f, WinH = 680f, ScreenW = 768f, ScreenH = 578f, Bezel = 6f;
|
||||
private static float ListW => L.Wide ? 276f : 190f;
|
||||
private static float RowW => L.Wide ? ListW - 52f : ListW - 12f;
|
||||
private static float TextW => L.Wide ? 456f : 540f;
|
||||
|
||||
private static int _chapter;
|
||||
private static readonly List<GameObject> _picked = new List<GameObject>();
|
||||
private static readonly List<Image> _clear = new List<Image>();
|
||||
private static readonly List<PledgerSkin.RowDef> _rows = new List<PledgerSkin.RowDef>();
|
||||
|
||||
private static string Title(string chapter)
|
||||
{
|
||||
int end = chapter.Length;
|
||||
foreach (var m in new[] { ":", ": ", "(", " (" })
|
||||
{
|
||||
int i = chapter.IndexOf(m, StringComparison.Ordinal);
|
||||
if (i > 0 && i < end) end = i;
|
||||
}
|
||||
return chapter.Substring(0, end).TrimEnd();
|
||||
}
|
||||
|
||||
private static string Body(string chapter)
|
||||
{
|
||||
foreach (var m in new[] { ":", ": " })
|
||||
{
|
||||
int i = chapter.IndexOf(m, StringComparison.Ordinal);
|
||||
int p = chapter.IndexOf("(", StringComparison.Ordinal);
|
||||
if (i > 0 && (p < 0 || i < p || p > 40)) return chapter.Substring(i + m.Length);
|
||||
}
|
||||
return chapter;
|
||||
}
|
||||
|
||||
private static string _key = "guide.web3.text", _nameKey = "guide.web3.title";
|
||||
private static readonly Dictionary<string, int> _chapterOf = new Dictionary<string, int>();
|
||||
|
||||
public static void Open() => Show("guide.web3.text", "guide.web3.title");
|
||||
|
||||
private static void Show(string key, string nameKey)
|
||||
{
|
||||
_key = key; _nameKey = nameKey;
|
||||
_chapter = _chapterOf.TryGetValue(key, out var ch0) ? ch0 : 0;
|
||||
Reopen();
|
||||
}
|
||||
|
||||
private static void Reopen()
|
||||
{
|
||||
_chapterOf[_key] = _chapter;
|
||||
var chapters = TuningText.Render(L.T(_key)).Replace("¶", "\n\n").Split('§');
|
||||
if (_chapter >= chapters.Length) _chapter = 0;
|
||||
var b = CustomUIManager.Window(Id, L.T(_nameKey));
|
||||
if (b == null) return;
|
||||
_picked.Clear(); _clear.Clear(); _rows.Clear();
|
||||
b.SetSize(WinW, WinH).SetDraggable(true).SetCloseOnEscape(true).UseMachineryStyle();
|
||||
b.BeginPanel(ScreenW + Bezel * 2, ScreenH + Bezel * 2, TextAnchor.MiddleCenter, Bezel + 3f, 0f);
|
||||
var bezel = b.Last.image;
|
||||
b.BeginPanel(ScreenW, ScreenH, TextAnchor.UpperLeft, 12f, 4f);
|
||||
var screen = b.CurrentContainer;
|
||||
var paper = b.Last.image;
|
||||
b.BeginRow(10f);
|
||||
b.BeginPanel(ListW, -1f, TextAnchor.UpperLeft, 0f, 0f);
|
||||
_clear.Add(b.Last.image);
|
||||
b.BeginScroll(ScreenH - 30f);
|
||||
_clear.Add(b.Last.image);
|
||||
for (int i = 0; i < chapters.Length; i++)
|
||||
{
|
||||
int k = i;
|
||||
PledgerSkin.TableRow(b, RowW, 30f, new[] { RowW }, new[] { TextAnchor.MiddleLeft },
|
||||
new[] { Title(chapters[i]) }, i == _chapter, () => { _chapter = k; Reopen(); }, _rows, _clear);
|
||||
}
|
||||
b.End();
|
||||
b.End();
|
||||
b.BeginPanel(TextW, -1f, TextAnchor.UpperLeft, 6f, 6f);
|
||||
_clear.Add(b.Last.image);
|
||||
b.BeginScroll(ScreenH - 30f);
|
||||
_clear.Add(b.Last.image);
|
||||
b.AddHeader(Title(chapters[_chapter]));
|
||||
b.AddSeparator();
|
||||
b.AddLabel(Body(chapters[_chapter]));
|
||||
b.End();
|
||||
b.End();
|
||||
b.End();
|
||||
b.End();
|
||||
b.End();
|
||||
var win = b.Show();
|
||||
Log.Guard("手册外观", () => PledgerSkin.Apply(win, screen, bezel, paper, _picked, _clear, _rows));
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,107 @@
|
||||
using System;
|
||||
using Decentralized.Domain;
|
||||
|
||||
namespace Decentralized
|
||||
{
|
||||
/// <summary>
|
||||
/// 收黑币的上门顾客(游戏的对话顾客):游戏里出了事,有人拿着来路不明的币折价换现金,见 <see cref="HotCoins"/>。
|
||||
/// 一天最多一位。收下:付现金,币进已连接的钱包(PSC、CRT 全额带污点);钓鱼执法:现金被没收并记销赃罪证,币不会到。
|
||||
/// </summary>
|
||||
public static class HotCoinSeller
|
||||
{
|
||||
private static int seenDay = -1;
|
||||
|
||||
public static void Subscribe()
|
||||
{
|
||||
ModHook.OnGenerateCustomerLate += OnGenerate;
|
||||
ModHelper.AddDebugFunction(ModInfo.Id, ModInfo.Name, "Hot coin seller (test)", () => Log.Guard("收黑币(测试)", () =>
|
||||
{
|
||||
var d = Session.Data;
|
||||
string[] assets = { Assets.CRT, Assets.PSC, Assets.Ponero };
|
||||
var c = Create(assets[d.Rng.Range(0, assets.Length - 1)]);
|
||||
if (c == null) return;
|
||||
PlayerStore.Instance.currentClientInstance = null;
|
||||
PlayerStore.Instance.storeClientManager.clientStack.Insert(0, c);
|
||||
PlayerStore.Instance.TryCallNextClient();
|
||||
}));
|
||||
}
|
||||
|
||||
public static void Unsubscribe() => ModHook.OnGenerateCustomerLate -= OnGenerate;
|
||||
|
||||
private static void OnGenerate(StoreClientManager manager)
|
||||
{
|
||||
var d = Session.Data;
|
||||
if (d == null || !Unlock.IsUnlocked || !d.Connected) return;
|
||||
Log.Guard("收黑币", () =>
|
||||
{
|
||||
int day = StoreStation.GetDayCounter();
|
||||
if (day == seenDay) return;
|
||||
seenDay = day;
|
||||
bool ponero = Unlock.BlackUnlocked && BlackMarket.DeskOpen(StoreReputation.GetBMReputation());
|
||||
string asset = HotCoins.Pick(Night.ActiveEvents(), ponero, d.Rng);
|
||||
if (asset == null) return;
|
||||
var c = Create(asset);
|
||||
if (c != null) manager.AddClient(c);
|
||||
});
|
||||
}
|
||||
|
||||
private static StoreClient Create(string asset)
|
||||
{
|
||||
var d = Session.Data;
|
||||
bool crackdown = Night.ActiveEvents().Contains(MarketEvent.Crackdown);
|
||||
var o = HotCoins.Make(asset, Session.Price(asset), Session.Rent(), crackdown, d.Rng);
|
||||
if (o == null) return null;
|
||||
var c = new StoreClient
|
||||
{
|
||||
identifier = "pd_hot_coins", displayName = L.T("hot.name"),
|
||||
spriteName = asset == Assets.CRT ? SpriteDict.GetRandomBMMaleSpriteName() : asset == Assets.PSC ? SpriteDict.GetRandomRevSpriteName() : SpriteDict.GetRandomShadySpriteName(),
|
||||
clientIntent = StoreClient.ClientIntent.DIALOGUE,
|
||||
};
|
||||
// 选项的动作先于下一句执行:在动作里结算,再把卖家的回话换成结果
|
||||
var yes = new Dialogue();
|
||||
var reply = yes.SetText("PLAYER", L.T("hot.say.yes")).NextDialogue();
|
||||
reply.SetText(c.displayName, L.T("hot.refused")).SetEndAction(Leave);
|
||||
var no = new Dialogue();
|
||||
no.SetText("PLAYER", L.T("hot.say.no")).NextDialogue().SetText(c.displayName, L.T("hot.refused")).SetEndAction(Leave);
|
||||
c.mainDialogue.SetText(c.displayName, L.T("hot.intro." + asset)).NextDialogue()
|
||||
.SetText(c.displayName, L.T("hot.offer", Fmt.Num(o.Qty), asset, Fmt.Credits(o.Value), Fmt.Credits(o.Cash)))
|
||||
.AddChoice(DirectoryMaster.Item("yes"), L.T("hot.choice.yes"), "", yes, () => reply.SetText(c.displayName, L.T(Accept(o))))
|
||||
.AddChoice(DirectoryMaster.Item("cancel"), L.T("hot.choice.no"), "", no, null);
|
||||
ModHelper.SetClientSource(c, ModInfo.Id);
|
||||
c.AddBasicDialog();
|
||||
c.CompleteClientCreation();
|
||||
Log.Info($"收黑币上门:{o.Qty:0.##} {asset},市值 {o.Value:0},要价 {o.Cash}{(o.Sting ? "(钓鱼执法)" : "")}");
|
||||
return c;
|
||||
}
|
||||
|
||||
/// <summary>选了收下:现金不够或没连钱包就作罢;钓鱼执法没收现金、记罪证;否则付现金、币进钱包。返回卖家回话的键。</summary>
|
||||
private static string Accept(HotOffer o)
|
||||
{
|
||||
string line = "hot.refused";
|
||||
Log.Guard("收黑币成交", () =>
|
||||
{
|
||||
var d = Session.Data;
|
||||
if (!d.Connected) { line = "hot.nowallet"; return; }
|
||||
if (PlayerStore.Instance.playerCash < o.Cash) { line = "hot.nocash"; return; }
|
||||
ModHelper.AddCredit(-o.Cash, false);
|
||||
if (o.Sting)
|
||||
{
|
||||
PlayerStore.Instance.secData.CommitCrime("FENCING", (int)Math.Min(Tuning.CrimeEventCap, o.Cash));
|
||||
line = "hot.sting";
|
||||
Log.Info($"收黑币:钓鱼执法,现金 {o.Cash} 没收,记销赃罪证");
|
||||
}
|
||||
else
|
||||
{
|
||||
HotCoins.Receive(d.Hot, o);
|
||||
d.Chain(ChainAddress.Make(d.Rng.NextUInt()), d.Hot.Address, o.Asset, o.Qty);
|
||||
line = "hot.done";
|
||||
Log.Info($"收黑币:{o.Qty:0.##} {o.Asset} 进 {WalletWindow.NameOf(d.Hot)},付现金 {o.Cash},钱包污点 {d.Hot.Taint:0}");
|
||||
}
|
||||
Session.Save();
|
||||
});
|
||||
return line;
|
||||
}
|
||||
|
||||
private static void Leave() => DialogUIManager.Instance.CurrentClientLeave();
|
||||
}
|
||||
}
|
||||
@@ -15,17 +15,38 @@ namespace Decentralized
|
||||
{
|
||||
public const string Terminal = "pd_terminal";
|
||||
public const string Rig = "pd_rig";
|
||||
public const string Guide = "pd_gpu_guide";
|
||||
public const string GpuPrefix = "pd_gpu_";
|
||||
public const string HwWallet = "pd_hw_wallet";
|
||||
public const string KeyDrive = "pd_key_drive";
|
||||
/// <summary>硬件钱包被动过手脚(供应链投毒)。外观、说明都不显示。</summary>
|
||||
public const string PoisonTag = "PD_POISONED";
|
||||
|
||||
public const string HealthTag = "PD_HEALTH";
|
||||
public const string FakeTag = "PD_FAKE_OF";
|
||||
public const string RefurbTag = "PD_REFURBISHED";
|
||||
public const string DeadTag = "PD_DEAD";
|
||||
public const string LookTag = "PD_LOOK", BackTag = "PD_BACK", SeedTag = "PD_SEED", ClaimTag = "PD_CLAIM", ExposedTag = "PD_EXPOSED", MarkupTag = "PD_MARKUP", EditedTag = "PD_EDITED";
|
||||
|
||||
public static Action OpenTerminal;
|
||||
public static Action OpenGpuHandbook;
|
||||
/// <summary>硬件钱包拖到交易终端上:添加一个钱包(参数:是否被投毒)。</summary>
|
||||
public static Action<bool> AddWallet;
|
||||
public static Func<bool> CanAddWallet;
|
||||
|
||||
public static void Subscribe() => ModHook.OnModItemDirectoryInit += Register;
|
||||
public static void Unsubscribe() => ModHook.OnModItemDirectoryInit -= Register;
|
||||
public static void Subscribe()
|
||||
{
|
||||
ModHook.OnModItemDirectoryInit += Register;
|
||||
ModHook.OnLeavingStoreEarly += SweepFront;
|
||||
ModHook.OnGoingSleepEarly += SweepFront;
|
||||
}
|
||||
|
||||
public static void Unsubscribe()
|
||||
{
|
||||
ModHook.OnModItemDirectoryInit -= Register;
|
||||
ModHook.OnLeavingStoreEarly -= SweepFront;
|
||||
ModHook.OnGoingSleepEarly -= SweepFront;
|
||||
}
|
||||
|
||||
public static string GpuId(string model) => GpuPrefix + model.ToLowerInvariant();
|
||||
|
||||
@@ -35,7 +56,13 @@ namespace Decentralized
|
||||
{
|
||||
dir.Add(Terminal, CreateTerminal);
|
||||
dir.Add(Rig, CreateRig);
|
||||
foreach (var spec in Hardware.Specs.Values.Where(s => !s.Asic))
|
||||
WrapElectronics(dir);
|
||||
WrapTurbos(dir);
|
||||
dir.Add(Guide, CreateGuide);
|
||||
dir.Add(HwWallet, CreateHwWallet);
|
||||
dir.Add(KeyDrive, CreateKeyDrive);
|
||||
AsicItems.Register(dir);
|
||||
foreach (var spec in Hardware.Specs.Values.Where(s => !s.Asic && !s.Scrap))
|
||||
{
|
||||
var s = spec;
|
||||
dir.Add(GpuId(s.Model), () => CreateGpu(s));
|
||||
@@ -60,31 +87,278 @@ namespace Decentralized
|
||||
return item;
|
||||
}
|
||||
|
||||
/// <summary>显卡鉴定手册:型号对照、序列号规则、外观折扣。做法同游戏里的鉴定手册(海明威鉴定指南):纸张图、文档类型、拖放音效。</summary>
|
||||
private static GameItem CreateGuide()
|
||||
{
|
||||
var item = ItemDirectory.CreateEmptyItem(Guide);
|
||||
item.SetSpriteAndShape("Items/items_misc", "guide1");
|
||||
item.EnableTag("DOCUMENT");
|
||||
item.SetGameItemType("DOCUMENT");
|
||||
item.EnableTag("GUIDE_PAPER_TAG");
|
||||
BookHelper.InitPaperGuide(item);
|
||||
item.name = L.T("item.guide.name");
|
||||
item.shortDescription = L.T("item.guide.desc");
|
||||
item.mayActivateSlotItemFunc = (_, _, _) => true;
|
||||
item.canActivateSlotItemFunc = (_, _, _) => true;
|
||||
item.onActivateSlotItemFunc = (_, _, _) => Log.Guard("打开鉴定手册", () => OpenGpuHandbook?.Invoke());
|
||||
item.unitValue = 50;
|
||||
item.EnableTag(GeneralHelper.IMPORTANT_TAG);
|
||||
item.EnableTag(TypeHelper.NOT_FOR_RESALE);
|
||||
ModHelper.SetSource(item, ModInfo.Id, ModInfo.Name);
|
||||
return item;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// PLEDGER 硬件钱包:和游戏里的升级材料一样,拖到交易终端上用掉,钱包 +1。杰克逊博士卖的是正品;
|
||||
/// Web3 商城卖的便宜一些,外观和说明完全一样,其中一部分被动过手脚(<see cref="PoisonTag"/>)。
|
||||
/// </summary>
|
||||
private static GameItem CreateHwWallet()
|
||||
{
|
||||
var item = ItemDirectory.CreateEmptyItem(HwWallet);
|
||||
item.SetSpriteAndShapeFromMod(ModInfo.Id, "hw_wallet");
|
||||
item.name = L.T("item.hwwallet.name");
|
||||
item.shortDescription = L.T("item.hwwallet.desc");
|
||||
item.unitValue = Tuning.WalletJacksonPrice;
|
||||
item.SetGameItemType("MATERIAL");
|
||||
item.maySelectSlotItemFunc = (_, _, _) => true;
|
||||
item.canSelectSlotItemFunc = (_, _, _) => true;
|
||||
item.mayThisTargetItemFunc = (Func<GameItem, GameItem, bool>)Delegate.Combine(item.mayThisTargetItemFunc, (Func<GameItem, GameItem, bool>)((s, t) => CanTarget(t)));
|
||||
item.canThisTargetItemFunc = (Func<GameItem, GameItem, bool>)Delegate.Combine(item.canThisTargetItemFunc, (Func<GameItem, GameItem, bool>)((s, t) => CanTarget(t)));
|
||||
item.onThisTargetItemFunc = (Action<GameItem, GameItem>)Delegate.Combine(item.onThisTargetItemFunc, (Action<GameItem, GameItem>)((s, t) => Log.Guard("添加硬件钱包", () =>
|
||||
{
|
||||
if (!CanTarget(t)) return;
|
||||
bool poisoned = s.IsTag(PoisonTag);
|
||||
s.Destroy();
|
||||
AddWallet?.Invoke(poisoned);
|
||||
})));
|
||||
ModHelper.SetSource(item, ModInfo.Id, ModInfo.Name);
|
||||
return item;
|
||||
}
|
||||
|
||||
/// <summary>Tumbler 的密钥盘:违禁品(高),搜查时被翻出来按价值记罪证。</summary>
|
||||
private static GameItem CreateKeyDrive()
|
||||
{
|
||||
var item = ItemDirectory.CreateEmptyItem(KeyDrive);
|
||||
item.SetSpriteAndShapeFromMod(ModInfo.Id, "key_drive");
|
||||
item.name = L.T("item.keydrive.name");
|
||||
item.shortDescription = L.T("item.keydrive.desc");
|
||||
item.unitValue = Tuning.TumblerDriveValue;
|
||||
ContrabandHelper.InitContrabandItem(item, 3);
|
||||
ModHelper.SetSource(item, ModInfo.Id, ModInfo.Name);
|
||||
return item;
|
||||
}
|
||||
|
||||
private static bool CanTarget(GameItem t) => t != null && t.identifier == Terminal && (CanAddWallet?.Invoke() ?? false);
|
||||
|
||||
public static GameItem NewHwWallet(bool poisoned)
|
||||
{
|
||||
var item = ModHelper.SpawnItem(HwWallet);
|
||||
if (item != null && poisoned) item.EnableTag(PoisonTag);
|
||||
return item;
|
||||
}
|
||||
|
||||
// ---------- 显卡 ----------
|
||||
|
||||
/// <summary>RZX70 → "RZX 70",RZX80Ti → "RZX 80 Ti",RZ6800 → "RZ 6800"。</summary>
|
||||
/// <summary>RTX70 → "RTX 70",RX800 → "RX 800"。</summary>
|
||||
public static string DisplayModel(string model) => Regex.Replace(Regex.Replace(model, @"(?<=[A-Za-z])(?=\d)", " "), @"(?<=\d)(?=[A-Z])", " ");
|
||||
|
||||
private static GameItem CreateGpu(HardwareSpec spec)
|
||||
{
|
||||
var item = ItemDirectory.CreateEmptyItem(GpuId(spec.Model));
|
||||
item.SetSpriteAndShapeFromMod(ModInfo.Id, spec.Brand == Hardware.Probidia ? "gpu_probidia" : "gpu_pmd");
|
||||
item.SetGameItemType("ELECTRONIC");
|
||||
item.SetGameItemType("MATERIAL");
|
||||
InspectableHelper.InitInspectableItem(item);
|
||||
item.onLoaded = Refresh;
|
||||
// 右键"切换"翻面;外观差异用叠加图画在同一张底图上
|
||||
item.EnableTag(ToggleAppearanceHelper.TOGGLE_APPEARANCE_TAG);
|
||||
item.mayToggleSlotItemFunc = (_, _, _) => true;
|
||||
item.canToggleSlotItemFunc = (_, _, _) => true;
|
||||
item.onToggleSlotItemFunc = (toggled, _, _) => Log.Guard("显卡翻面", () =>
|
||||
{
|
||||
Flip(toggled);
|
||||
});
|
||||
item.getItemSpriteModifierForItemFunc = Overlays;
|
||||
// 摆给顾客的时候,顾客可能看出说法与实物对不上
|
||||
item.onSlotAddItemFunc = (Action<GameItem, GameInventory, SlotMarker>)Delegate.Combine(item.onSlotAddItemFunc,
|
||||
(Action<GameItem, GameInventory, SlotMarker>)((it, _, __) => Log.Guard("顾客验货", () => OnOffered(it))));
|
||||
ModHelper.SetSource(item, ModInfo.Id, ModInfo.Name);
|
||||
Refresh(item);
|
||||
return item;
|
||||
}
|
||||
|
||||
/// <summary>按给定的状态造一张卡(二手卡、假卡):写入标签并生成外观。</summary>
|
||||
public static GameItem NewCard(string model, double health, string fakeOf, Rng rng, DealerKind? seller = null, int markupPct = 0)
|
||||
{
|
||||
var item = ModHelper.SpawnItem(GpuId(model));
|
||||
var u = new Unit { Model = model, FakeOf = fakeOf, Health = health, Look = CardLook.Generate(rng, health, fakeOf != null, Hardware.Specs[model].Tier, fakeOf != null ? Hardware.Specs[fakeOf].Tier : Hardware.Specs[model].Tier) };
|
||||
if (health >= 100 && fakeOf == null) u.Look.Sticker = 0; // 全新卡:封条完好
|
||||
Store(item, u);
|
||||
if (seller != null)
|
||||
{
|
||||
GeneralHelper.SetItemOwned(item, false); // 卖家的货:买下之前不属于玩家,说法才有效
|
||||
SetClaim(item, CardLabels.DealerClaim(u, seller.Value, rng), 0, markupPct);
|
||||
}
|
||||
return item;
|
||||
}
|
||||
|
||||
// ---------- 标签栏:卖家的说法与指出 ----------
|
||||
|
||||
private static object checkedClient;
|
||||
private static readonly HashSet<int> checkedItems = new HashSet<int>();
|
||||
|
||||
/// <summary>被顾客看穿时的信誉损失:骗的价差每满一周房租扣 1 点,最少 1,最多 25。</summary>
|
||||
public static int RepLoss(long gap) => (int)Math.Max(1, Math.Min(Tuning.RepLossMax, Math.Round(gap / (double)Math.Max(1, PlayerStore.Instance.rentValue))));
|
||||
|
||||
/// <summary>
|
||||
/// 自己的卡摆给想买的顾客:说法里隐瞒的每一项,顾客有 50% 的概率看出来(型号档次不符的必看出来,供电口和风扇数一眼可见);看出来就拆穿这一项(价格回到真实情况),
|
||||
/// 并且掉一点信誉。每位顾客对每张卡只看一次。说法比实际更差(把好卡说差了)顾客不会去指。
|
||||
/// </summary>
|
||||
public static void OfferForTest(GameItem item) { checkedItems.Clear(); OnOffered(item, true); }
|
||||
|
||||
private static void OnOffered(GameItem item, bool force = false)
|
||||
{
|
||||
if (item.IsTag(DeadTag) || !GeneralHelper.IsItemOwned(item) || (!force && !item.IsRootedInBackInv())) return;
|
||||
var ci = PlayerStore.Instance.currentClientInstance;
|
||||
var client = ci?.GetClientBlueprint();
|
||||
if (client == null || (client.clientIntent != StoreClient.ClientIntent.BUY && client.clientIntent != StoreClient.ClientIntent.SELLNBUY)) return;
|
||||
var claim = GetClaim(item);
|
||||
if (claim == null) return;
|
||||
if (!ReferenceEquals(checkedClient, ci)) { checkedClient = ci; checkedItems.Clear(); }
|
||||
if (!checkedItems.Add(item.uniqueId)) return;
|
||||
var u = ToUnit(item);
|
||||
int exposed = Exposed(item);
|
||||
int lies = CardLabels.Lies(u, claim.Value, exposed);
|
||||
if (lies == 0) return;
|
||||
var rng = Session.Data.Rng;
|
||||
int found = 0;
|
||||
foreach (int r in CardLabels.Rows)
|
||||
if ((lies & r) != 0 && rng.Chance((r == CardLabels.RowCount || r == CardLabels.RowPin) ? Tuning.CustomerSpotTierMismatch : Tuning.CustomerSpotChance))
|
||||
{
|
||||
found |= r;
|
||||
if (r != CardLabels.RowSpec && CardLabels.IsEvidence(r, claim.Value, Claim.Truth(u))) found |= CardLabels.RowSpec | CardLabels.RowCount | CardLabels.RowPin | CardLabels.RowPrint | CardLabels.RowSerial;
|
||||
}
|
||||
if (found == 0) return;
|
||||
long before = item.unitValue;
|
||||
item.ModifyTag(ExposedTag, t => t.Enable().SetInt(exposed | found));
|
||||
Refresh(item);
|
||||
int rep = RepLoss(before - item.unitValue);
|
||||
string faction = string.IsNullOrEmpty(client.clientFaction) || StoreReputation.GetStoreReputation(client.clientFaction) == null ? "FACTION_LOWER_LEVEL" : client.clientFaction;
|
||||
StoreReputation.ModReputation(faction, -rep);
|
||||
EmporiumAudioPlayer.Instance?.audioFail?.Play();
|
||||
Log.Info($"顾客看出标签不实:{found},价格 {item.unitValue},信誉 −{rep}");
|
||||
DialogUIManager.Instance.StartDialogue(new Dialogue().SetText("CLIENT", L.T((found & CardLabels.RowSpec) != 0 ? "cust.fake." + rng.Range(1, 2) : "cust.worn." + rng.Range(1, 2))));
|
||||
}
|
||||
|
||||
/// <summary>标签上的说法;没有说法的卡(自己挖出来、正规渠道的新卡)一律按真实情况算。</summary>
|
||||
public static Claim? GetClaim(GameItem item)
|
||||
{
|
||||
if (!item.IsTag(ClaimTag)) return null;
|
||||
var c = Claim.Decode(item.GetTagReadonly(ClaimTag).GetString());
|
||||
return string.IsNullOrEmpty(c.Model) ? (Claim?)null : c;
|
||||
}
|
||||
|
||||
/// <summary>已指出的标签。型号一旦被拆穿,四个真伪行(型号、供电与风扇、序列号、丝印)一起亮出真实情况。</summary>
|
||||
public static int Exposed(GameItem item)
|
||||
{
|
||||
int e = item.IsTag(ExposedTag) ? item.GetTagReadonly(ExposedTag).GetInt() : 0;
|
||||
if ((e & CardLabels.RowSpec) != 0) e |= CardLabels.RowSpec | CardLabels.RowCount | CardLabels.RowPin | CardLabels.RowSerial | CardLabels.RowPrint;
|
||||
return e;
|
||||
}
|
||||
|
||||
public static void SetClaim(GameItem item, Claim claim, int exposed, int markupPct = 0)
|
||||
{
|
||||
item.ModifyTag(ClaimTag, t => t.Enable().SetString(claim.Encode()));
|
||||
item.ModifyTag(ExposedTag, t => t.Enable().SetInt(exposed));
|
||||
if (markupPct != 0) item.ModifyTag(MarkupTag, t => t.Enable().SetInt(markupPct));
|
||||
Refresh(item);
|
||||
}
|
||||
|
||||
/// <summary>现在标签上写的型号:说法里的型号,被拆穿之后是真实芯片。</summary>
|
||||
public static string BelievedModel(GameItem item, Unit u)
|
||||
{
|
||||
var c = GetClaim(item);
|
||||
if (c == null) return u.Model;
|
||||
return (Exposed(item) & CardLabels.RowSpec) != 0 ? (u.FakeOf ?? u.Model) : c.Value.Model;
|
||||
}
|
||||
|
||||
/// <summary>玩家指出一个标签:记下来,说法改回真实情况;返回 0 说法属实、1 隐瞒了不利的情况、2 拆穿假货。</summary>
|
||||
public static int Point(GameItem item, int row)
|
||||
{
|
||||
var u = ToUnit(item);
|
||||
var claim = GetClaim(item) ?? Claim.Truth(u);
|
||||
int exposed = Exposed(item);
|
||||
int kind = CardLabels.Point(u, claim, row, ref exposed);
|
||||
item.ModifyTag(ExposedTag, t => t.Enable().SetInt(exposed));
|
||||
if (!item.IsTag(ClaimTag)) item.ModifyTag(ClaimTag, t => t.Enable().SetString(claim.Encode()));
|
||||
Refresh(item);
|
||||
if (item.IsTag("APPRAISAL_ITEM")) AppraisalHelper.SetDefaultAppraisalValue(item, (int)item.unitValue);
|
||||
return kind;
|
||||
}
|
||||
|
||||
/// <summary>用标签机改说法(随便改):这一项重新算作"没人指出过"。</summary>
|
||||
public static void EditClaim(GameItem item, int row, int value, string model = null)
|
||||
{
|
||||
var u = ToUnit(item);
|
||||
var claim = GetClaim(item) ?? Claim.Truth(u);
|
||||
claim = row == CardLabels.RowSpec ? new Claim { Model = model ?? claim.Model, Fan = claim.Fan, Fingers = claim.Fingers, Bracket = claim.Bracket, Print = claim.Print, Sticker = claim.Sticker } : claim.With(row, value);
|
||||
int exposed = Exposed(item) & ~row;
|
||||
item.EnableTag(EditedTag);
|
||||
SetClaim(item, claim, exposed);
|
||||
}
|
||||
|
||||
/// <summary>说明:算力和耗电按标称写;成色在归玩家之前只给粗略等级(要看外观自己判断),归玩家之后给精确健康度。</summary>
|
||||
private static string Desc(GameItem item, Unit u)
|
||||
{
|
||||
var label = Hardware.Specs[BelievedModel(item, u)];
|
||||
string cond = GeneralHelper.IsItemOwned(item)
|
||||
? Mathf.RoundToInt((float)u.Health) + "%"
|
||||
: L.T(u.Health >= 85 ? "item.gpu.grade.1" : u.Health >= 60 ? "item.gpu.grade.2" : u.Health >= 35 ? "item.gpu.grade.3" : "item.gpu.grade.4");
|
||||
return L.T("item.gpu.desc", Fmt.Num(label.DisplayHash), Fmt.Num(label.Kj), cond);
|
||||
}
|
||||
|
||||
private static void SyncValue(GameItem item)
|
||||
{
|
||||
if (item.IsTag(DeadTag)) return;
|
||||
// 买下之后卖家的说法作废:卡回到真实情况,除非玩家用标签机自己改过
|
||||
if (GeneralHelper.IsItemOwned(item) && item.IsTag(ClaimTag) && !item.IsTag(EditedTag))
|
||||
{
|
||||
item.ModifyTag(ClaimTag, t => t.Disable());
|
||||
item.ModifyTag(ExposedTag, t => t.Disable());
|
||||
item.ModifyTag(MarkupTag, t => t.Disable());
|
||||
}
|
||||
var u = ToUnit(item);
|
||||
string desc = Desc(item, u);
|
||||
if (item.shortDescription != desc) item.shortDescription = desc;
|
||||
string name = L.T("item.gpu.name", Hardware.Specs[BelievedModel(item, u)].Brand, DisplayModel(BelievedModel(item, u)));
|
||||
if (item.name != name) item.name = name;
|
||||
long value = CardLabels.Value(u, GetClaim(item), Exposed(item));
|
||||
if (!GeneralHelper.IsItemOwned(item) && item.IsTag(MarkupTag)) value = Math.Max(1, (long)Math.Round(value * (1 + item.GetTagReadonly(MarkupTag).GetInt() / 100.0)));
|
||||
if (item.unitValue != value) item.unitValue = value;
|
||||
}
|
||||
|
||||
public static Unit ToUnit(GameItem item)
|
||||
{
|
||||
string model = item.identifier.Substring(GpuPrefix.Length);
|
||||
model = Hardware.Specs.Keys.First(k => k.ToLowerInvariant() == model);
|
||||
bool asic = AsicItems.Is(item);
|
||||
string model = item.identifier.Substring(asic ? AsicItems.Prefix.Length : GpuPrefix.Length);
|
||||
model = Hardware.Specs.Keys.FirstOrDefault(k => k.ToLowerInvariant() == model) ?? (asic ? "M1" : "RTX60");
|
||||
var u = new Unit { Model = model, Health = 100 };
|
||||
if (asic)
|
||||
{
|
||||
// 矿机没有外观、没有真假:不记外观种子,算力、损耗、暴毙都按规格表
|
||||
if (item.IsTag(HealthTag)) u.Health = item.GetTagReadonly(HealthTag).GetDouble();
|
||||
u.Dead = item.IsTag(DeadTag);
|
||||
return u;
|
||||
}
|
||||
if (item.IsTag(HealthTag)) u.Health = item.GetTagReadonly(HealthTag).GetDouble();
|
||||
if (item.IsTag(FakeTag)) u.FakeOf = item.GetTagReadonly(FakeTag).GetString();
|
||||
u.Refurbished = item.IsTag(RefurbTag);
|
||||
u.Dead = item.IsTag(DeadTag);
|
||||
if (item.IsTag(LookTag))
|
||||
{
|
||||
var enc = item.GetTagReadonly(LookTag).GetString();
|
||||
u.Look = CardLook.Legacy(enc, CardLook.Decode(enc), u.Model, u.FakeOf); // 旧存档的假卡补上风扇数、供电口破绽
|
||||
}
|
||||
// 外观种子:没有记录的卡(正规渠道的新卡)用物品编号当种子,之后同样随损耗变旧
|
||||
u.Look.Seed = item.IsTag(SeedTag) ? (uint)item.GetTagReadonly(SeedTag).GetInt() : (uint)(item.uniqueId * 2654435761u) | 1u;
|
||||
return u;
|
||||
}
|
||||
|
||||
@@ -94,12 +368,18 @@ namespace Decentralized
|
||||
if (u.FakeOf != null) item.ModifyTag(FakeTag, s => s.Enable().SetString(u.FakeOf));
|
||||
if (u.Refurbished) item.EnableTag(RefurbTag);
|
||||
if (u.Dead) item.EnableTag(DeadTag);
|
||||
if (!AsicItems.Is(item))
|
||||
{
|
||||
item.ModifyTag(LookTag, s => s.Enable().SetString(u.Look.Encode()));
|
||||
item.ModifyTag(SeedTag, s => s.Enable().SetInt((int)u.Look.Seed));
|
||||
}
|
||||
Refresh(item);
|
||||
}
|
||||
|
||||
/// <summary>按标签更新名字、说明、价值和图:显示的是标签上的型号(假卡也显示被冒充的型号)。</summary>
|
||||
public static void Refresh(GameItem item)
|
||||
{
|
||||
if (AsicItems.Is(item)) { AsicItems.Refresh(item); return; }
|
||||
var u = ToUnit(item);
|
||||
var label = u.Label;
|
||||
if (u.Dead)
|
||||
@@ -107,12 +387,69 @@ namespace Decentralized
|
||||
item.name = L.T("item.gpu.burnt.name", label.Brand, DisplayModel(label.Model));
|
||||
item.shortDescription = L.T("item.gpu.burnt.desc");
|
||||
item.unitValue = Math.Max(1, label.Price / 20);
|
||||
item.SetSpriteAndShapeFromMod(ModInfo.Id, "gpu_burnt");
|
||||
item.SetSpriteAndShapeFromMod(ModInfo.Id, item.IsTag(BackTag) ? "gpu_burnt_b" : "gpu_burnt_f");
|
||||
return;
|
||||
}
|
||||
item.name = L.T("item.gpu.name", label.Brand, DisplayModel(label.Model));
|
||||
item.shortDescription = L.T("item.gpu.desc", Fmt.Num(label.DisplayHash), Fmt.Num(label.Kj), Mathf.RoundToInt((float)u.Health));
|
||||
item.unitValue = Math.Max(1, (long)Math.Round(label.Price * u.Health / 100));
|
||||
item.SetSpriteAndShapeFromMod(ModInfo.Id, LookKeys(item, new List<string>()));
|
||||
SyncValue(item);
|
||||
}
|
||||
|
||||
public static bool IsBack(GameItem item) => item.IsTag(BackTag);
|
||||
|
||||
public static void Flip(GameItem item)
|
||||
{
|
||||
if (IsBack(item)) item.ModifyTag(BackTag, t => t.Disable()); else item.EnableTag(BackTag);
|
||||
Refresh(item);
|
||||
}
|
||||
|
||||
/// <summary>当前面的底图名与叠加图名:正面三个维度,背面丝印与贴纸;烧毁的卡不叠。</summary>
|
||||
/// <summary>实物上的风扇数:由真实芯片的档次决定(低档次的板子套高档次的壳,风扇数露馅)。</summary>
|
||||
public static int FansOf(Unit u) => u.ObservedCount;
|
||||
|
||||
public static string LookKeys(GameItem item, List<string> overlays)
|
||||
{
|
||||
var u = ToUnit(item);
|
||||
var l = u.Appearance;
|
||||
bool back = IsBack(item);
|
||||
string brand = u.Label.Brand == Hardware.Probidia ? "gpu_probidia" : "gpu_pmd";
|
||||
if (u.Dead) return back ? "gpu_burnt_b" : "gpu_burnt_f";
|
||||
if (!back)
|
||||
{
|
||||
if (l.Fan > 0) overlays.Add($"gpu_ov_fan{l.Fan}_{FansOf(u)}");
|
||||
if (l.Fingers > 0) overlays.Add("gpu_ov_fin" + l.Fingers);
|
||||
if (l.Bracket > 0) overlays.Add("gpu_ov_brk1");
|
||||
}
|
||||
else
|
||||
{
|
||||
// 丝印:0 标称型号;1 印的是真实芯片型号;2 标称型号但字歪(重印过)
|
||||
string model = l.Print == 1 && u.FakeOf != null ? u.FakeOf : u.Model;
|
||||
overlays.Add((l.Print == 2 ? "gpu_ov_txs_" : "gpu_ov_txt_") + model.ToLowerInvariant());
|
||||
if (l.Sticker == 2) overlays.Add("gpu_ov_stk2");
|
||||
}
|
||||
return brand + (back ? "_b" : $"_f_p{u.ObservedPin}n{u.ObservedCount}");
|
||||
}
|
||||
|
||||
public static Sprite ModSprite(string key)
|
||||
{
|
||||
var mod = ModLoader.Mods.Find(m => m.Manifest.ID.Equals(ModInfo.Id));
|
||||
return mod != null && mod.Sprites.TryGetValue(key, out var sprite) ? sprite : null;
|
||||
}
|
||||
|
||||
/// <summary>物品栏里的外观叠加图。</summary>
|
||||
private static List<ItemSpriteModifier> Overlays(GameItem item)
|
||||
{
|
||||
var list = new List<ItemSpriteModifier>();
|
||||
SyncValue(item); // 归属变化(买下)后价格随之变回真实价值
|
||||
if (item.IsTag(DeadTag)) return list;
|
||||
var keys = new List<string>();
|
||||
LookKeys(item, keys);
|
||||
int priority = 0;
|
||||
foreach (var k in keys)
|
||||
{
|
||||
var sprite = ModSprite(k);
|
||||
if (sprite != null) list.Add(new ItemSpriteModifier(sprite, Vector2.zero, 0, false, priority++, false, Color.white));
|
||||
}
|
||||
return list;
|
||||
}
|
||||
|
||||
// ---------- 矿架 ----------
|
||||
@@ -124,17 +461,26 @@ namespace Decentralized
|
||||
private static GameItem CreateRig()
|
||||
{
|
||||
var battery = new GameSlotInventory();
|
||||
var upgrade = new GameSlotInventory();
|
||||
var modules = new GameGridInventory(MachineHelper.DEFAULT_MODULE_BAY_CONFIG, 7);
|
||||
// 显卡每张 2×2 格:一列 2 格宽的格子,每个槽两行;未解锁的行不可放
|
||||
// 显卡每张 3×2 格:3 格宽的格子,每张卡 3×2 格,每个槽两行;未解锁的行不可放
|
||||
var cards = new GameGridInventory(RigSlots.Shape(RigSlots.Base), RigSlots.CellWidth);
|
||||
// 状态面板:显卡数、耗电、算力(只读)
|
||||
var stCount = new MachineryText("", 6, TMPro.HorizontalAlignmentOptions.Left, false);
|
||||
var stPower = new MachineryText("", 6, TMPro.HorizontalAlignmentOptions.Left, false);
|
||||
var stHash = new MachineryText("", 6, TMPro.HorizontalAlignmentOptions.Left, false);
|
||||
GameItem rigItem = null;
|
||||
var status = new MachineryStack(true, 6).Add(stCount).Add(stPower).Add(stHash).Add(Payout.Build(() => rigItem, out var stAddr));
|
||||
var window = MachineHelper.CreateMachineryWindow(true,
|
||||
MachineHelper.PowerPanel(battery),
|
||||
MachineHelper.Panel(L.T("rig.label.modules"), modules, "module"),
|
||||
MachineHelper.Panel(L.T("rig.label.cards"), cards, "cards"),
|
||||
MachineHelper.Panel(L.T("rig.label.upgrade"), upgrade, "upgrade"));
|
||||
MachineHelper.Panel(L.T("rig.label.status"), status, "status", false));
|
||||
var rig = ItemDirectory.CreateEmptyItem(Rig).SetContentWindow(window);
|
||||
rig.SetSpriteAndShapeFromMod(ModInfo.Id, "rig");
|
||||
rigItem = rig;
|
||||
RigStatus.Add(rig, new[] { stCount, stPower, stHash });
|
||||
Payout.Register(rig, stAddr);
|
||||
RigInv.Remove(rig); RigInv.Add(rig, Tuple.Create(cards, (GameInventory)modules));
|
||||
rig.name = L.T("item.rig.name");
|
||||
rig.unitValue = Tuning.RigPrice;
|
||||
MachineHelper.SetupBatterySlot(battery, rig);
|
||||
@@ -146,13 +492,6 @@ namespace Decentralized
|
||||
cards.mayInventoryAddItemFunc = (item, _) => GeneralHelper.IsItemOwned(item) && IsGpu(item) && !item.IsTag(DeadTag);
|
||||
cards.onSlotAddItemEndFunc = (_, _, _) => UpdateRig(rig, modules, cards);
|
||||
cards.onSlotRemoveItemEndFunc = (_, _, _) => UpdateRig(rig, modules, cards);
|
||||
// 升级槽:只收下一级需要的电子元件,放进去立刻投入(计入进度),攒够解锁一个显卡槽
|
||||
upgrade.mayInventoryAddItemFunc = (item, _) =>
|
||||
{
|
||||
var need = RigSlots.Next(SlotsOf(rig));
|
||||
return GeneralHelper.IsItemOwned(item) && need != null && item.identifier == need.Value.Item;
|
||||
};
|
||||
upgrade.onSlotAddItemEndFunc = (item, _, _) => Log.Guard("矿架升级槽位", () => TakeUpgrade(rig, upgrade, cards, modules, item));
|
||||
rig.onLoaded = _ => { ApplySlots(rig, cards); UpdateRig(rig, modules, cards); };
|
||||
rig.onCycleEndEarlySlotItemFunc = (_, _, _) => Log.Guard("矿架扣电", () => NightDraw(rig, battery, modules, cards));
|
||||
ModHelper.SetSource(rig, ModInfo.Id, ModInfo.Name);
|
||||
@@ -168,18 +507,83 @@ namespace Decentralized
|
||||
rig.contentWindow?.Validate();
|
||||
}
|
||||
|
||||
private static void TakeUpgrade(GameItem rig, GameSlotInventory upgradeSlot, GameGridInventory cards, GameInventory modules, GameItem item)
|
||||
/// <summary>
|
||||
/// 电子元件作用在矿架上:游戏按“材料作用于目标”判断,元件自己的判断函数对矿架一律为否(三方判断取与),
|
||||
/// 所以要在元件上加一个对矿架为真的判断。用原版目录里的工厂造元件,再补上这三个函数。
|
||||
/// </summary>
|
||||
private static void WrapElectronics(ModItemDirectory dir)
|
||||
{
|
||||
try
|
||||
{
|
||||
foreach (var id in new[] { "common_electronic", "rare_electronic", "hypertech_electronic" })
|
||||
{
|
||||
var vanilla = DirectoryMaster.GetFactory<GameItem>(id);
|
||||
if (vanilla == null) { Log.Warn($"[Rig] 找不到原版 {id}"); continue; }
|
||||
var make = vanilla;
|
||||
dir.Set(id, () =>
|
||||
{
|
||||
var it = make();
|
||||
Func<GameItem, GameItem, bool> can = (src, t) => t != null && ((t.identifier == Rig && CanUpgradeWith(t, src)) || AsicItems.CanRepairWith(t, src));
|
||||
it.mayThisTargetItemFunc = (Func<GameItem, GameItem, bool>)Delegate.Combine(it.mayThisTargetItemFunc, can);
|
||||
it.canThisTargetItemFunc = (Func<GameItem, GameItem, bool>)Delegate.Combine(it.canThisTargetItemFunc, can);
|
||||
it.onThisTargetItemFunc = (Action<GameItem, GameItem>)Delegate.Combine(it.onThisTargetItemFunc, (Action<GameItem, GameItem>)((src, t) =>
|
||||
{
|
||||
if (t != null && t.identifier == Rig && CanUpgradeWith(t, src)) Log.Guard("矿架升级槽位", () => TakeUpgrade(t, src));
|
||||
else if (AsicItems.CanRepairWith(t, src)) Log.Guard("矿机修理", () => AsicItems.TakeRepair(t, src));
|
||||
}));
|
||||
return it;
|
||||
});
|
||||
Log.Info($"[Rig] 已给 {id} 加上升级矿架的作用");
|
||||
}
|
||||
}
|
||||
catch (Exception ex) { Log.Error("[Rig] 包装电子元件失败:" + ex); }
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 涡轮增压器不能作用于矿架和 ASIC 矿机:它们带"标准机器"标签,原版涡轮只看这个标签,还会手动触发目标的夜间结算(等于白天多扣一次电)。
|
||||
/// 在原版涡轮工厂外包一层,对这两类目标返回否;是替换判断函数而不是追加(追加是"或",原来的"是"还会生效)。
|
||||
/// </summary>
|
||||
private static void WrapTurbos(ModItemDirectory dir)
|
||||
{
|
||||
foreach (var id in new[] { "turbo_booster", "turbo_booster_adv", "turbo_booster_hypertech" })
|
||||
{
|
||||
var make = DirectoryMaster.GetFactory<GameItem>(id);
|
||||
if (make == null) { Log.Warn($"[Rig] 找不到原版 {id}"); continue; }
|
||||
dir.Set(id, () =>
|
||||
{
|
||||
var it = make();
|
||||
var may = it.mayThisTargetItemFunc;
|
||||
var can = it.canThisTargetItemFunc;
|
||||
it.mayThisTargetItemFunc = (s, t) => !IsMiner(t) && (may?.Invoke(s, t) ?? false);
|
||||
it.canThisTargetItemFunc = (s, t) => !IsMiner(t) && (can?.Invoke(s, t) ?? false);
|
||||
return it;
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
private static bool IsMiner(GameItem t) => t != null && (t.identifier == Rig || AsicItems.Is(t));
|
||||
|
||||
private static readonly System.Runtime.CompilerServices.ConditionalWeakTable<GameItem, Tuple<GameGridInventory, GameInventory>> RigInv = new System.Runtime.CompilerServices.ConditionalWeakTable<GameItem, Tuple<GameGridInventory, GameInventory>>();
|
||||
|
||||
private static bool CanUpgradeWith(GameItem rig, GameItem src)
|
||||
{
|
||||
var need = RigSlots.Next(SlotsOf(rig));
|
||||
return src != null && rig.identifier == Rig && need != null && src.identifier == need.Value.Item && GeneralHelper.IsItemOwned(src);
|
||||
}
|
||||
|
||||
private static void TakeUpgrade(GameItem rig, GameItem item)
|
||||
{
|
||||
if (!RigInv.TryGetValue(rig, out var inv)) return;
|
||||
var cards = inv.Item1; var modules = inv.Item2;
|
||||
int slots = SlotsOf(rig);
|
||||
int progress = rig.IsTag(ProgressTag) ? rig.GetTagReadonly(ProgressTag).GetInt() : 0;
|
||||
int before = slots;
|
||||
int took = RigSlots.Insert(ref slots, ref progress, item.identifier, item.unitCount);
|
||||
int took = RigSlots.Insert(ref slots, ref progress, item.identifier, 1);
|
||||
if (took <= 0) return;
|
||||
rig.ModifyTag(SlotsTag, s => s.Enable().SetInt(slots));
|
||||
rig.ModifyTag(ProgressTag, s => s.Enable().SetInt(progress));
|
||||
// 消耗收下的件数;放不下的部分留在升级槽里(玩家取回)
|
||||
if (took >= item.unitCount) { upgradeSlot.Expel(item); item.Destroy(); }
|
||||
else item.GetSplitItem(took).Destroy();
|
||||
if (item.unitCount <= 1) item.Destroy(); else item.GetSplitItem(1).Destroy();
|
||||
if (slots != before)
|
||||
{
|
||||
ApplySlots(rig, cards);
|
||||
@@ -215,6 +619,8 @@ namespace Decentralized
|
||||
double hash = Cards(cards).Select(ToUnit).Sum(u => u.Hash(b));
|
||||
int slots = SlotsOf(rig);
|
||||
rig.shortDescription = L.T("item.rig.desc", slots, Fmt.Num(hash * 10), kj);
|
||||
RigStatus.Show(rig, Cards(cards).Count, slots, kj, hash * 10);
|
||||
Payout.Refresh(rig);
|
||||
var next = RigSlots.Next(slots);
|
||||
if (next != null)
|
||||
{
|
||||
@@ -234,6 +640,7 @@ namespace Decentralized
|
||||
/// <summary>夜间早段:按矿架上的显卡总耗电(含模块效果)从电池扣电;扣电成功,登记今晚参与挖矿的显卡和模块效果。</summary>
|
||||
private static void NightDraw(GameItem rig, GameSlotInventory battery, GameInventory modules, GameInventory cards)
|
||||
{
|
||||
if (!Session.TonightDrawn.Add(rig.uniqueId)) return;
|
||||
var list = Cards(cards).Where(c => !c.IsTag(DeadTag)).ToList();
|
||||
Session.TonightRigs++;
|
||||
if (list.Count == 0) return;
|
||||
@@ -242,7 +649,7 @@ namespace Decentralized
|
||||
if (battery.childItems.Count == 0 || !PowerHelper.DrawPowerSource(battery.childItem, kj)) return;
|
||||
Session.TonightPoweredRigs++;
|
||||
Session.TonightKj += kj;
|
||||
foreach (var c in list) Session.TonightCards.Add(new KeyValuePair<GameItem, ModuleBonus>(c, b));
|
||||
foreach (var c in list) { Session.TonightCards.Add(new KeyValuePair<GameItem, ModuleBonus>(c, b)); Session.TonightMachine[c] = rig; }
|
||||
UpdateRig(rig, modules, cards);
|
||||
}
|
||||
|
||||
@@ -250,6 +657,38 @@ namespace Decentralized
|
||||
/// 放进储藏区(游戏 EmporiumTryAdd 的默认目标,放不下时游戏自己找位置)。
|
||||
/// 不放柜台:测试中柜台上的物品过夜后会消失(未在正常流程中确认);ModHelper.MoveItemTo* 放满时会静默失败。
|
||||
/// </summary>
|
||||
/// <summary>优先放进机器区(machine_bay*)的格子里,没有位置时退回 <see cref="Give"/>。矿架这类机器该待在机器区。</summary>
|
||||
public static void GiveToMachineBay(GameItem item)
|
||||
{
|
||||
GeneralHelper.SetItemOwned(item, true);
|
||||
var e = EmporiumEntry.Instance;
|
||||
if (e?.invElement != null)
|
||||
foreach (var box in e.invElement.childItems.Where(i => i.identifier != null && i.identifier.StartsWith("machine_bay")).ToList())
|
||||
if (GraphUtils.CanAccept(box, item) && GraphUtils.TryAcceptAll(box, item) == 0) return;
|
||||
Give(item);
|
||||
}
|
||||
|
||||
/// <summary>放到前台(解锁送的东西第一眼能看到);前台放不下时退回储藏区。游戏离店和过夜会清空前台,<see cref="SweepFront"/> 在那之前把 mod 的物品收进储藏区。</summary>
|
||||
public static void GiveToFront(GameItem item)
|
||||
{
|
||||
GeneralHelper.SetItemOwned(item, true);
|
||||
var front = EmporiumEntry.Instance?.frontInvinvElement;
|
||||
if (front != null && GraphUtils.CanAccept(front, item) && GraphUtils.TryAcceptAll(front, item) == 0) return;
|
||||
Give(item);
|
||||
}
|
||||
|
||||
/// <summary>离店、睡觉前:前台上属于 mod 的物品收进储藏区(游戏随后会清空前台,没拿走的终端、钱包会丢)。</summary>
|
||||
private static void SweepFront()
|
||||
{
|
||||
Log.Guard("收起前台的 mod 物品", () =>
|
||||
{
|
||||
var e = EmporiumEntry.Instance;
|
||||
if (e?.frontInvinvElement == null || e.invElement == null) return;
|
||||
foreach (var it in e.frontInvinvElement.childItems.ToList())
|
||||
if (it.identifier != null && it.identifier.StartsWith("pd_") && GeneralHelper.IsItemOwned(it)) GraphUtils.TryAcceptAll(e.invElement, it);
|
||||
});
|
||||
}
|
||||
|
||||
public static void Give(GameItem item)
|
||||
{
|
||||
GeneralHelper.SetItemOwned(item, true);
|
||||
|
||||
@@ -12,9 +12,20 @@ namespace Decentralized
|
||||
{
|
||||
Items.Subscribe();
|
||||
Items.OpenTerminal = TerminalWindow.Open;
|
||||
Items.OpenGpuHandbook = () => GpuGuide.Open();
|
||||
ModHook.OnModAssetsLoaded += GpuGuide.OnAssetsLoaded;
|
||||
Items.AddWallet = TerminalWindow.AddWallet;
|
||||
Items.CanAddWallet = TerminalWindow.CanAddWallet;
|
||||
Settings.DefineWhenReady(ModHelper.GetConfig(ModInfo.Id));
|
||||
Unlock.Register();
|
||||
Night.Subscribe();
|
||||
DealerStock.Subscribe();
|
||||
UsedDealerClient.Subscribe();
|
||||
CoinCustomers.Subscribe();
|
||||
HotCoinSeller.Subscribe();
|
||||
BlackDelivery.Subscribe();
|
||||
TumblerStory.Subscribe();
|
||||
GpuInspectView.Ensure();
|
||||
ModHook.OnGameLoadedLate += Session.Load;
|
||||
ModHook.OnNewGameStarted += OnNewGame;
|
||||
Log.Info($"{ModInfo.Name} {ModInfo.Version} 已启用");
|
||||
@@ -25,6 +36,14 @@ namespace Decentralized
|
||||
Items.Unsubscribe();
|
||||
Night.Unsubscribe();
|
||||
DealerStock.Unsubscribe();
|
||||
UsedDealerClient.Unsubscribe();
|
||||
CoinCustomers.Unsubscribe();
|
||||
HotCoinSeller.Unsubscribe();
|
||||
BlackDelivery.Unsubscribe();
|
||||
TumblerStory.Unsubscribe();
|
||||
GpuInspectView.Remove();
|
||||
WalletDriver.Remove();
|
||||
ModHook.OnModAssetsLoaded -= GpuGuide.OnAssetsLoaded;
|
||||
ModHook.OnGameLoadedLate -= Session.Load;
|
||||
ModHook.OnNewGameStarted -= OnNewGame;
|
||||
}
|
||||
|
||||
@@ -0,0 +1,980 @@
|
||||
# Probably Decentralized localization table: German (de)
|
||||
# AI translation, not proofread. Source: en.csv. Format: key,text (text may be quoted; \n is a line break).
|
||||
upgrade.tab,Web3
|
||||
upgrade.title,Web3-Governance-Community
|
||||
upgrade.desc,"Mitglieder erhalten ein Handelsterminal, eine Hardware-Wallet, ein Mining-Rig, eine RTX-60-Grafikkarte und ein Handbuch zur Grafikkartenprüfung. Das Terminal umfasst die Bank, die Poinbase-Börse sowie die Seiten Web3, Mining und Wallets. Weitere Karten und Rigs verkauft Dr. Jackson."
|
||||
item.terminal.name,Handelsterminal
|
||||
item.terminal.desc,"Wallet, Poinbase-Börse und nächtlicher Mining-Bericht."
|
||||
item.rig.name,Mining-Rig
|
||||
item.rig.desc,Platz für bis zu {0} Grafikkarten. Hashrate: {1} MH/s. Verbrauch: {2} kJ/Tag.
|
||||
rig.label.modules,Module
|
||||
item.rig.modules,"Module: Hashrate {0}, Verbrauch {1}, Verschleiß {2}."
|
||||
item.rig.next,Slot {0}: {1} auf das Mining-Rig ziehen ({2}/{3}).
|
||||
mat.common_electronic,Einfache Elektronik
|
||||
mat.rare_electronic,Seltene Elektronik
|
||||
rig.label.cards,Grafikkarten
|
||||
item.gpu.name,{0} {1}
|
||||
item.gpu.desc,Nenn-Hashrate: {0} MH/s. Nennverbrauch: {1} kJ/Tag. Zustand: {2}.
|
||||
item.gpu.burnt.name,Durchgebrannte {0} {1}
|
||||
item.gpu.burnt.desc,Diese Karte funktioniert nicht mehr.
|
||||
term.title,Handelsterminal
|
||||
tab.report,Bericht
|
||||
wallet.line,{0}: {1} (ca. {2} Credits)
|
||||
wallet.empty,Die Wallet ist leer.
|
||||
wallet.total,Gesamtwert: {0} Credits
|
||||
wallet.taint,Kontaminierter Wert: {0} Credits
|
||||
trade.amount,Betrag
|
||||
trade.deposit,Credits als CRC einzahlen
|
||||
trade.withdraw,CRC als Credits auszahlen
|
||||
trade.pair,{0}/{1} ({2})
|
||||
trade.price,Preis: {0}
|
||||
trade.buy,Kaufen
|
||||
trade.sell,Verkaufen
|
||||
venue.Exchange,Poinbase
|
||||
venue.Dex,DEX
|
||||
venue.Darknet,Darknet
|
||||
msg.amount,Betrag eingeben.
|
||||
msg.balance,Nicht genügend Guthaben.
|
||||
msg.trade,"{0} {1} gezahlt, {2} {3} erhalten."
|
||||
msg.deposit,{0} Credits als CRC eingezahlt.
|
||||
msg.cashout,{0} Credits erhalten. Steuer: {1} Credits.
|
||||
msg.aml_light,Compliance-Prüfung: {0} Credits an kontaminierten Geldern wurden einbehalten.
|
||||
msg.aml_heavy,Compliance-Prüfung: {0} Credits an kontaminierten Geldern wurden beschlagnahmt und an Security gemeldet.
|
||||
report.none,Noch kein Mining-Bericht vorhanden.
|
||||
report.day,Nacht von Tag {0}
|
||||
report.rigs,Rigs mit Strom: {0} von {1}
|
||||
report.hash,Hashrate: {0} MH/s (Netzwerk {1} MH/s)
|
||||
report.mined,Geschürft: {0} PSC (ca. {1} Credits)
|
||||
report.energy,Energieverbrauch: {0} kJ
|
||||
report.burnt,Durchgebrannte Karten: {0}
|
||||
report.price,PSC-Preis: {0} Credits
|
||||
nightlog.mined,Mining-Rigs haben {0} PSC geschürft.
|
||||
nightlog.burnt,{0} ist durchgebrannt.
|
||||
coinpay.line,Abgemacht. {0} {1}.
|
||||
nightlog.coinpay,Zahlungen in Coins ergaben {0} Credits; die Coins wurden an die Hot-Wallet übertragen.
|
||||
nightlog.unpowered,Mining-Rigs oder Miner ohne Strom: {0}.
|
||||
news.open.title,Poinbase listet PSC
|
||||
news.open.desc,Die Börse Poinbase auf der Oberen Ebene listet nun PSC gegen CRC. Stationsweit steigt die Nachfrage nach Grafikkarten.
|
||||
news.halving.title,PSC-Blockbelohnung halbiert
|
||||
news.halving.desc,Miner erhalten nun pro Nacht nur noch halb so viele Coins.
|
||||
appraisal.gpu,Grafikkarte
|
||||
dealer.name,Gebrauchthardware-Dealer
|
||||
dealer.line1.1,Karten aus einer Mining-Auflösung. Der Zustand steht neben dem Namen.
|
||||
dealer.line1.2,"Ein paar Mining-Karten, günstig abzugeben."
|
||||
dealer.line1.3,Unterwegs aufgelesen. Preis aus erster Hand.
|
||||
dealer.line2.1,"Sieh selbst, dreh sie um und schau dir die Rückseite an."
|
||||
dealer.line2.2,Keine Garantie. Vor dem Mitnehmen prüfen.
|
||||
dealer.line2.3,"Wenn du sie haben willst, lässt sich über den Preis reden."
|
||||
inspect.flip.back,Umdrehen
|
||||
inspect.flip.front,Vorderseite
|
||||
item.gpu.grade.1,wie neu
|
||||
item.gpu.grade.2,ordentlich
|
||||
item.gpu.grade.3,deutlich gebraucht
|
||||
item.gpu.grade.4,stark abgenutzt
|
||||
point.none.1,Daran ist nichts falsch. Du hast dich wohl verguckt.
|
||||
point.none.2,"Wo denn? Denk dir nichts aus, wenn du nicht kaufst."
|
||||
point.worn.1,"…Na gut, der Mangel ist da. Ich geh etwas mit dem Preis runter."
|
||||
point.worn.2,"Scharfe Augen. Gut, machen wir diesen Preis."
|
||||
point.fake.1,"…Erwischt. Ist umgeflasht. Ich nehme den Preis für das, was sie wirklich ist."
|
||||
point.fake.2,"Tss, nicht der Originalchip. Na gut, zum Preis des echten Chips."
|
||||
lbl.fan.0,Lüfterblätter sauber
|
||||
lbl.fan.1,Lüfterblätter verstaubt
|
||||
lbl.fan.2,Lüfterblatt abgesplittert
|
||||
lbl.fingers.0,Glänzend
|
||||
lbl.fingers.1,Matt
|
||||
lbl.fingers.2,Oxidiert
|
||||
lbl.print.0,Stimmt mit Modell überein
|
||||
lbl.print.1,Anderes Modell aufgedruckt
|
||||
lbl.print.2,"Nachgedruckt, schief"
|
||||
lbl.said," (Verkäufer meinte: {0})"
|
||||
lbl.point,Beanstanden
|
||||
lbl.edit,Bearbeiten
|
||||
cust.fake.1,"Das ist nicht das, was auf dem Etikett steht. Willst du mir eine Fälschung andrehen?"
|
||||
cust.fake.2,Das Modell passt nicht. Das ist nicht der angebliche Chip.
|
||||
cust.worn.1,Das hast du nicht angegeben. Die Mängel hast du verschwiegen.
|
||||
cust.worn.2,Der Zustand auf dem Etikett stimmt nicht. Nicht zu diesem Preis.
|
||||
lbl.row.fan,Lüfterblätter
|
||||
lbl.row.fingers,Kontakte
|
||||
lbl.row.bracket,Slotblende
|
||||
lbl.row.print,Rückseiten-Aufdruck
|
||||
lbl.row.serial,Seriennummer
|
||||
lbl.row.seal,Siegel
|
||||
lbl.bracket.0,Intakt
|
||||
lbl.bracket.1,Zerkratzt
|
||||
lbl.serial.0,Gültig
|
||||
lbl.serial.1,Ungültiger Werkscode oder falsche Länge
|
||||
lbl.serial.2,Modellcode passt nicht zum Modell
|
||||
lbl.seal.0,Intakt
|
||||
lbl.seal.2,Fehlt
|
||||
item.guide.name,Handbuch zur Grafikkartenprüfung
|
||||
item.guide.desc,Ein Handbuch zur Prüfung von Grafikkarten auf Echtheit und Wert.
|
||||
lbl.row.spec,Modell
|
||||
news.prehalving.title,PSC-Halving steht bevor
|
||||
news.prehalving.desc,In drei Tagen erhalten Miner pro Nacht nur noch halb so viele Coins. Halter erwarten steigende Kurse.
|
||||
tab.home,Übersicht
|
||||
tab.bank,Bank
|
||||
tab.poinbase,Poinbase
|
||||
tab.web3,Web3
|
||||
home.enter,Öffnen
|
||||
home.open,Öffnen
|
||||
home.summary,Credits {0} | On-Chain-Vermögen ca. {1} Credits
|
||||
home.lastnight,"Nacht von Tag {0}: {1} PSC geschürft, {2} / {3} Rigs mit Strom"
|
||||
entry.bank,Bank
|
||||
entry.bank.l1,"Einzahlungen, Auszahlungen, Miete"
|
||||
entry.bank.l2,Credits {0}
|
||||
entry.poinbase,Poinbase
|
||||
entry.poinbase.l1,Regulierte Börse
|
||||
entry.poinbase.l2,PSC {0} Credits
|
||||
entry.web3,Web3
|
||||
entry.web3.l2,Ca. {0} Credits
|
||||
entry.help,Hilfe
|
||||
entry.help.l1,Web3-Handbuch
|
||||
bank.cash,Credits: {0}
|
||||
bank.rent,"Miete: {0} Credits, fällig in {1} Tg."
|
||||
bank.crc,Poinbase-Konto (CRC): {0}
|
||||
poin.account,"Poinbase-Konto: CRC {0}, PSC {1}"
|
||||
avg.line,{0} Ø-Kaufpreis: {1} Credits
|
||||
avg.short,Ø-Kauf {0}
|
||||
avg.none,—
|
||||
col.asset,Asset
|
||||
col.amount,Betrag
|
||||
col.value,Wert
|
||||
col.avg,Ø-Kauf
|
||||
bank.cash.k,Credits
|
||||
bank.rent.k,Miete
|
||||
bank.rent.v,"{0}, fällig in {1} Tg."
|
||||
bank.crc.k,Poinbase-Konto (CRC)
|
||||
poin.account.h,Poinbase-Konto
|
||||
trade.h,Handel
|
||||
web3.wallet.h,On-Chain-Wallet
|
||||
stable.ok,Gekoppelt
|
||||
stable.depeg,Entkoppelt
|
||||
stable.warn,Warnung: Staking-Reservedeckung knapp
|
||||
stable.spiral,Kollaps
|
||||
aml.taint,Konto-Kontaminationsanteil: {0}%
|
||||
mixer.h,Mixer
|
||||
mixer.ok,Status: Normalbetrieb
|
||||
mixer.sanctioned,Status: sanktioniert (noch {0} Tag(e)). Währenddessen abgehobene Coins werden markiert.
|
||||
mixer.pending,Ausstehende Einzahlungen
|
||||
mixer.none,Keine ausstehenden Einzahlungen.
|
||||
mixer.col.taint,Kontamination
|
||||
mixer.col.ready,Fällig
|
||||
mixer.day,Tag {0}
|
||||
mixer.deposit,Einzahlung
|
||||
mixer.balance,Guthaben: {1} {0}
|
||||
mixer.rounds,Runden
|
||||
mixer.preview,"Voraussichtlich {0} {1} zurück, Kontamination um ca. {2}% gesenkt, fällig an Tag {3}."
|
||||
mixer.go,In Mixer einzahlen
|
||||
mixer.min,Einzahlungen müssen mindestens {0} Credits wert sein.
|
||||
mixer.done,{0} {1} eingezahlt; Rückerhalt an Tag {2}.
|
||||
mixer.upgrade.title,Mixer
|
||||
mixer.upgrade.desc,Schaltet den Mixer auf der Graunetz-Seite des Terminals frei: Kontaminierte Coins einzahlen und Tage später mit reduzierter Kontamination zurückerhalten. Auszahlungen frisch gemixter Coins werden strenger geprüft; bei Razzien kann der Mixer sanktioniert werden und währenddessen abgehobene Coins werden markiert.
|
||||
news.sanction.title,Mixer auf Sanktionsliste gesetzt
|
||||
news.sanction.desc,Security hat eine Reihe von Mixing-Diensten sanktioniert. In den nächsten Tagen aus Mixern abgehobene Gelder gelten als verdächtig.
|
||||
nightlog.mixer,Mixer zahlte {0} {1} zurück; Kontamination {2} -> {3}.
|
||||
nightlog.mixer_flag," (während Sanktionen abgehoben; Adresse markiert)"
|
||||
nightlog.mixer_rug,Der Mixer-Betreiber ist untergetaucht: {0} {1} kehrten nie zurück.
|
||||
web3.sub.trade,Handel
|
||||
gray.sub.mixer,Mixer
|
||||
msg.frozen,"Diese Coins sind eingefroren, bis sie freigegeben werden."
|
||||
wallet.frozen,"{0}: {1} eingefroren, Freigabe an Tag {2}"
|
||||
nightlog.crt_freeze,Der Schwarzmarkt hat bei der Razzia Adressen übergeben: {0} deiner CRT sind bis Tag {1} eingefroren.
|
||||
nightlog.thaw,Eingefrorene {0} {1} freigegeben.
|
||||
news.crtfreeze.title,Schwarzmarkt friert für Razzia einige CRT-Adressen ein
|
||||
news.crtfreeze.desc,"Gerüchten zufolge hat der Schwarzmarkt Security eine Liste von CRT-Adressen übergeben, um in Ruhe gelassen zu werden. Halter mit niedrigem Ansehen werden eher eingefroren."
|
||||
black.upgrade.title,Web3-Shop
|
||||
black.upgrade.desc,"Schaltet den Shop auf der Graunetz-Seite des Terminals frei: der On-Chain-Zweig der Schwarzmarkt-Fraktion. Wöchentlich wechselnde Schmuggelware, gelegentlich Hightech-Waren und Grafikkarten (mit Aufpreis); per Sofortkauf erwerben oder bestellen und auf einen Kurier warten. Nur Coins (PSC, CRT, CRA, Ponero), kontaminierte Coins werden akzeptiert. Erfordert Schwarzmarkt-Ansehen; offline bei Razzien."
|
||||
black.offline,Der On-Chain-Zugang des Shops ist während der Razzia offline.
|
||||
black.closed,"Schwarzmarkt-Ansehen von {0} erforderlich, um den Shop zu betreten (aktuell {1})."
|
||||
black.sub.buy,Kaufen
|
||||
black.shop.h,Spot-Theke
|
||||
black.rep,Schwarzmarkt-Ansehen {0}
|
||||
black.empty,Für diese Woche ausverkauft.
|
||||
black.offer,{0} x{1} {2} Credits
|
||||
black.buy,Kaufen
|
||||
black.bought,Deal abgeschlossen: {0} liegt im Lager.
|
||||
black.pay.h,Zahlung
|
||||
black.desk.h,Ponero-Schalter
|
||||
black.desk.left,Heute übrig: {0} (Limit {1})
|
||||
black.desk.price,Ponero-Preis: {0}
|
||||
black.desk.swap,Tausch
|
||||
black.desk.in,In Ponero
|
||||
black.desk.out,Aus Ponero
|
||||
black.desk.go,Tauschen
|
||||
black.desk.fail,"Tausch fehlgeschlagen: Guthaben, Limit oder Betrag ungültig."
|
||||
black.sub.orders,Bestellungen
|
||||
black.rugged,Die Plattform ist offline; Wiedereröffnung erst in {0} Tag(en).
|
||||
black.seller,"{1} Abschlüsse, {2}% positiv"
|
||||
black.orders.h,Bestellkatalog
|
||||
black.order,Bestellen
|
||||
black.mode.Escrow,Treuhand
|
||||
black.mode.Advance,Vorzeitige Freigabe
|
||||
black.ordered,"Bestellt: {0}, Ankunft an Tag {1}."
|
||||
black.mine.h,Meine Bestellungen
|
||||
black.mine.none,Noch keine Bestellungen.
|
||||
black.mine.line,"{0} ({1}, {2}): {3}, Tag {4}"
|
||||
black.state.Pending,unterwegs
|
||||
black.state.Ready,angekommen
|
||||
black.state.Done,abgeholt
|
||||
black.state.Refunded.scam,"Verkäufer geflohen, erstattet"
|
||||
black.state.Lost.scam,"Verkäufer geflohen, Geld weg"
|
||||
black.state.Lost.rug,"Plattform-Rug-Pull, Geld weg"
|
||||
black.state.Lost.intercept,abgefangen
|
||||
black.forum.h,Foren-Informationen
|
||||
black.forum.quiet,In letzter Zeit ruhig.
|
||||
black.forum.scam,"Jemand sagt, dass {0} das Geld nimmt und nie liefert."
|
||||
black.forum.rug,"Auszahlungen dauern in letzter Zeit länger, die Seite schaltet Sonderaktionen und viele Beschwerde-Threads wurden gelöscht."
|
||||
nightlog.bm.scam_refund,Schwarzmarkt: Verkäufer {0} ist geflohen; der Treuhandbetrag für {1} wurde erstattet.
|
||||
nightlog.bm.scam_loss,Schwarzmarkt: Verkäufer {0} hat die vorzeitige Freigabe kassiert und ist geflohen; {1} ist verloren ({2} Credits).
|
||||
nightlog.bm.intercept,Schwarzmarkt: Das Paket mit {0} wurde abgefangen; {1} Credits an Zahlungen verloren.
|
||||
nightlog.bm.rug,Schwarzmarkt: Plattform-Rug-Pull; die Gelder für {0} im Transit ({1}) sind verloren.
|
||||
nightlog.bm.reopen,Schwarzmarkt: Jemand hat an der alten Stelle wiedereröffnet.
|
||||
news.bmrug.title,Rug Pull auf Schwarzmarkt-Plattform
|
||||
news.bmrug.desc,Der On-Chain-Zugang des Schwarzmarkts ging über Nacht offline und löschte alle Gelder in Treuhand und vorzeitiger Freigabe aus. In wenigen Tagen wird ein neuer Zugang auftauchen.
|
||||
courier.name,Kurier
|
||||
courier.line1.1,Lieferung ist da.
|
||||
courier.line1.2,Ein Paket für dich.
|
||||
courier.line2.1,"Sag mir nicht, was drin ist. Ich will es gar nicht wissen."
|
||||
courier.line2.2,Hier abgestellt. Bin weg.
|
||||
gray.sub.black,Shop
|
||||
black.stock,Noch {0}
|
||||
black.price,{0} Credits
|
||||
black.noadvance,Keine vorzeitige Freigabe
|
||||
black.kind.gpu,GPU Zustand {0}%
|
||||
black.kind.Contraband.1,Schmuggelware (niedrig)
|
||||
black.kind.Contraband.2,Schmuggelware (mittel)
|
||||
black.kind.Contraband.3,Schmuggelware (hoch)
|
||||
black.kind.Tech,Hightech (Aufpreis)
|
||||
nightlog.bm.ready,"Schwarzmarkt: {0} eingetroffen; sobald du öffnest, kommt ein Kurier vorbei."
|
||||
guide.web3.title,Web3-Handbuch
|
||||
guide.web3.text,"Bank und Handel: Die Bankseite ist nur lesbar und zeigt Bargeld, Miete und das CRC auf dem Poinbase-Konto. Die Seite „Guthaben“ von Poinbase regelt Ein- und Auszahlungen; zuerst wird der Coin gewählt: CRC geht über das Bankkonto oder die Wallet, alle anderen Coins nur über die Wallet. Eine Einzahlung von der Bank wandelt Credits in CRC auf deinem Poinbase-Konto um; eine Auszahlung auf die Bank wandelt CRC zurück in Credits um und durchläuft eine Compliance-Prüfung, die die Kontamination des Poinbase-Kontos bewertet. Eine Auszahlung auf eine Wallet braucht die Zieladresse und mehrere Bestätigungen bis zur Gutschrift; die Gasgebühr ist fest auf Normal gesetzt und wird vom abgehenden Coin abgezogen. Ist das Adressformat oder die Prüfziffer falsch, wird abgelehnt; bei einer formal gültigen Adresse, die niemand nutzt, sind die Coins nach der Überweisung weg.¶Handel: PSC steht für Probably Stolen Coin, den durch Grafikkarten und Miner geschürften Coin. Der Poinbase-Spotmarkt hat zwei Paare, PSC/CRC und SPARK/CRC, je nach dem im Chart gewählten Coin. Käufe und Verkäufe werden beide als Menge des gehandelten Coins eingegeben; die Vorschau zeigt den gezahlten oder erhaltenen Notierungs-Coin, der Durchschnittspreis enthält die Gebühr, die Slippage nicht.¶Auf der Web3-Handelsseite lassen sich beliebige zwei Coins tauschen, stets über CRC als Zwischenschritt: Ist CRC eine Seite, läuft der Tausch über einen Pool, sonst über zwei Pools mit zwei Gebühren und sich addierender Slippage; die Vorschau zeigt Menge, Anzahl der Pools und Verlust. Stablecoin-Tausch (CRT oder CRA gegen CRC) läuft über Stable-Pools: {StableFee:%} Gebühr und kaum Slippage nahe der Bindung; beim Depeg wird die Liquidität dünner, beim Zusammenbruch wird sie abgezogen und die Slippage springt.§Hardware-Wallets: On-Chain-Coins liegen auf PLEDGER-Hardware-Wallets, jede mit eigenem Guthaben und eigener Kontamination. Eine Wallet ist ein Gegenstand: Ziehe sie auf das Handelsterminal, um sie zu laden. Öffne sie auf der Wallets-Seite des Terminals; verbinde und trenne sie oben rechts im Terminal. Der Handel der Web3-Seite sowie Shop und Mixer der Graunetz-Seite nutzen die verbundene Wallet; ohne Wallet oder ohne Verbindung sind sie nur lesbar und alle Guthaben zeigen 0. Kunden, die in Coins zahlen, zahlen auf die verbundene Wallet.¶Zahlungen (Shop, Mixer, Ponero-Schalter, Einstellgebühren) beginnen als Rechnung auf dem Handelsterminal; gib die Empfängeradresse auf der Wallet ein und halte zum Signieren ✓ gedrückt. Die letzten beiden Zeichen einer Adresse bilden eine Prüfsumme, sodass ein einzelner Tippfehler meist abgefangen wird; gelegentlich ist die Eingabe dennoch gültig und die Coins gehen an eine ungenutzte Adresse. Auch DEX-Swaps erfordern eine Signatur auf der Wallet.¶Poinbase ist ein Verwahrkonto; Einzahlungen erfolgen von der Wallet an die Einzahlungsadresse von Poinbase (nur PSC, CRC und SPARK; die regulierte Börse nimmt weder das CRT des Schwarzmarkts noch das CRA der Revolution, und die Wallet blockiert Überweisungen dieser Coins an die Einzahlungsadresse), Auszahlungen werden auf der Seite „Guthaben“ von Poinbase gestartet. Der Explorer auf der Wallets-Seite zeigt Überweisungen nach Adresse, ausschließlich tatsächlich erfolgte: jede Bewegung in und aus deinen Wallets (Überweisungen, DEX-Tausch und andere Vertragsaufrufe, Miner-Erträge, Auszahlungen, Coins, die andere dir schicken); Ponero ist ein Privacy Coin und erscheint nie. Weitere Hardware-Wallets verkauft Dr. Jackson; ziehe eine auf das Handelsterminal, um sie hinzuzufügen, bis zu {WalletMax}. Im Shop gibt es günstigere Exemplare. Eine nicht mehr benötigte Wallet kann auf der Wallets-Seite zerstört werden; ihre Coins sind dauerhaft verloren, ebenso alles, was danach an ihre Adresse gesendet wird.¶Überweisungen kosten Gasgebühren: langsam, normal oder schnell, und die Gas-Preise steigen und fallen im Wochenverlauf; bei Netzwerküberlastung steigen die Gasgebühren und langsame Transaktionen können aus dem Mempool fliegen. Vor dem Senden die vollständige Adresse prüfen.§Staking: Im Revolution-Pool gestakte CRA erzielen einen Tageszinssatz, der dem Einsatz zugeschlagen wird; eine Auszahlung erfordert einen vorherigen Antrag und vier Tage Wartezeit – ohne Zinsen während des Wartens und ohne vorzeitige Entnahme. CRA ist teilbesichert: Jedes CRA wird von CRC-Reserven der Revolution und vom Ausgleichstoken SPARK gedeckt; Reservedeckung und Besicherungsquote stehen auf der Staking-Seite. Zinsen werden in neuem, unbesichertem CRA gezahlt, das die Reservedeckung verwässert, umso schneller, je mehr gestakt ist; bei zu niedriger Deckung senkt die Revolution den Zinssatz. Die Revolution greift manchmal in die Reserve; zuvor gibt es Gerüchte, das ist das Vorzeichen. Fällt die Deckung danach unter {CraCrashRatio:%}, bricht das System zusammen: CRA ist binnen drei Tagen wertlos und vier Tage Entsperrung sind zu langLine truncated
|
||||
courier.odd1,...Paket ist da.
|
||||
courier.odd2,(Seine Hand bleibt in der Tasche.) Hier unterschreiben.
|
||||
courier.sign,Unterschreiben
|
||||
courier.refuse,Verweigern
|
||||
courier.signed,"Gut. Nicht bewegen, Security."
|
||||
courier.refused,"...Na gut, vergiss es."
|
||||
black.state.Lost.seized,beschlagnahmt
|
||||
black.state.Lost.refused,verweigert
|
||||
black.forum.easy,"Läuft zu glatt in letzter Zeit: Verkäufer liefern schneller denn je, und es gibt neue Konten, die noch nie jemand gesehen hat."
|
||||
black.forum.busted,"Man hört, dass {0} verhaftet wurde, und die Bestelldaten sind immer noch da."
|
||||
nightlog.bm.trap.honeypot,"Schwarzmarkt: Die Plattform wurde von den Strafverfolgern übernommen; dein {0} wurde zurückverfolgt, Straftat erfasst: {1}."
|
||||
nightlog.bm.trap.seller,"Schwarzmarkt: Ein Verkäufer wurde verhaftet und die Bestelldaten belasten dich: {0}, Straftat erfasst: {1}."
|
||||
tab.mining,Mining
|
||||
courier.sign.say,Ich unterschreibe.
|
||||
courier.refuse.say,Nehme ich nicht an. Zurückschicken.
|
||||
black.forum.busted_buyer,"Man hört, eine Gruppe Käufer wurde verhaftet, und die Verkaufsprotokolle sind noch auf der Plattform."
|
||||
nightlog.bm.sale_sold,Schwarzmarkt: Dein {0} wurde für {1} verkauft; Auszahlung an Tag {2}.
|
||||
nightlog.bm.sale_paid,"Schwarzmarkt: Auszahlung von {1} für {0} erhalten (CRT), Kontamination: {2}."
|
||||
nightlog.bm.sale_fake,"Schwarzmarkt: Der Käufer hat erkannt, dass {0} eine Fälschung ist, und retourniert; deine Bewertung ist gesunken."
|
||||
nightlog.bm.sale_rug,Schwarzmarkt: Die Plattform hat einen Rug Pull durchgezogen; dein {0} und die Auszahlung ({1}) sind weg.
|
||||
black.sub.sell,Verkaufen
|
||||
black.sell.h,Verkaufen
|
||||
black.sell.mult,Preismultiplikator
|
||||
black.sell.none,Keine verkaufbaren Gegenstände im Lager.
|
||||
black.sell.rating,Bewertung {0}%
|
||||
black.mine.sale,{0} Ref. {1} Preis {2} (x{3}): {4}
|
||||
black.sale.Listed,eingestellt
|
||||
black.sale.Paid,ausgezahlt
|
||||
black.sale.Lost,"Plattform-Rug-Pull, verloren"
|
||||
black.sale.Delisted,entfernt
|
||||
black.sale.Delisted.fake,Käufer erkannte Fälschung und retournierte
|
||||
black.kind.gpunew,GPU brandneu
|
||||
merchant.GpuNew,Neue GPUs
|
||||
merchant.GpuUsed,Gebrauchte GPUs
|
||||
merchant.Arms,Waffen
|
||||
merchant.Docs,Keycards & Chips
|
||||
merchant.Pharma,Pharma
|
||||
merchant.Bulk,Massenware
|
||||
black.days,{0} Tg. Lieferzeit
|
||||
black.sell.listedall,{0} Artikel eingestellt.
|
||||
merchant.Rigs,Rigs & Energie
|
||||
merchant.Modules,Module
|
||||
merchant.GunMods,Büchsenmacher-Teile
|
||||
merchant.Chem,Chemikalien
|
||||
merchant.Brewer,Brauen
|
||||
merchant.Farm,Hydroponik
|
||||
merchant.Husbandry,Tierhaltung
|
||||
merchant.Miner,Bergbaubedarf
|
||||
merchant.Water,Wasser
|
||||
merchant.Storage,Lagerung
|
||||
merchant.Tools,Werkzeuge
|
||||
merchant.Luxury,Luxusgüter
|
||||
black.kind.Goods,Waren
|
||||
merchant.Elite,Elite-Shop
|
||||
merchant.Personal,Privatverkäufer
|
||||
black.pay.confirm,Rechnung
|
||||
black.pay.to,Empfängeradresse: {0}
|
||||
black.pay.cancel,Stornieren
|
||||
pay.mix,Mixer {0} {1}
|
||||
pay.swap,Ponero-Schalter {0} {1}
|
||||
black.edit.cancel,Abbrechen
|
||||
merchant.Platform,Plattform
|
||||
black.platform.line,Plattform-Spot Sofortlieferung
|
||||
black.orders.in,Gekauft
|
||||
black.orders.out,Verkauf
|
||||
black.desk.pair,PONERO [Privacy Coin] Preis {0}
|
||||
black.pay.amount,Betrag: {0} {1} (ca. {2} Credits)
|
||||
black.pay.wallet,Mit Wallet bezahlen
|
||||
hw.total,Gesamt ≈ {0} Credits
|
||||
hw.pending.bill,Unbezahlt: {0}
|
||||
hw.pending.sign,Zu signieren: {0}
|
||||
hw.send,Senden
|
||||
hw.review,Signaturanfrage
|
||||
hw.to,Empfängeradresse
|
||||
hw.avail,Verfügbar {1} {0}
|
||||
hw.amount,Betrag
|
||||
hw.bill,Rechnung: {0} {1} {2}
|
||||
hw.fill,Rechnungsbetrag einfügen
|
||||
hw.next,✓ Weiter × Zurück
|
||||
hw.err.format,Ungültiges Adressformat.
|
||||
hw.err.checksum,Adress-Prüfsumme fehlerhaft.
|
||||
hw.err.self,Dies ist die eigene Adresse dieser Wallet.
|
||||
hw.err.asset,Die Rechnung verlangt {0}.
|
||||
hw.err.short,Weniger als der Rechnungsbetrag: {0} {1}.
|
||||
hw.err.nobill,Keine unbezahlte Rechnung für diesen Empfänger.
|
||||
hw.review.h,Überprüfung
|
||||
hw.contract,Contract-Aufruf
|
||||
hw.review.to,Empfängeradresse
|
||||
hw.review.amount,{0} {1} (ca. {2} Credits)
|
||||
hw.review.bill,Rechnung: {0}
|
||||
hw.review.unknown,Keine Transaktionshistorie für diese Adresse.
|
||||
hw.review.over,Überzahlung von {0} {1}; keine Rückerstattung.
|
||||
hw.hold,✓ zum Signieren halten × Ablehnen
|
||||
hw.tx.h,Transaktion
|
||||
hw.tx.signing,Wird signiert…
|
||||
hw.tx.mempool,Übertragen; wartet im Mempool…
|
||||
hw.tx.packed,In Block #{0} enthalten
|
||||
hw.tx.confirm,Block #{0} Bestätigung {1}/{2}
|
||||
hw.skip,Überspringen
|
||||
hw.done.h,Bestätigt
|
||||
hw.done.block,Block #{0}
|
||||
hw.done.sent,{0} {1} → {2}
|
||||
hw.done.void,Niemand nutzt diese Adresse. Die Coins sind verloren.
|
||||
hw.back,Zurück
|
||||
hw.rejected,Signatur auf der Wallet abgelehnt.
|
||||
hw.wait,Auf der Wallet bestätigen.
|
||||
hw.swap,Tausch {0} {1} → ca. {2} {3}
|
||||
tab.wallets,Wallets
|
||||
hw.wallet.n,Wallet {0}
|
||||
hw.review.own,Eigene Wallet: {0}
|
||||
hw.review.poinbase,Poinbase-Einzahlungsadresse
|
||||
poin.deposit,Einzahlungsadresse: {0}
|
||||
wallets.count,Wallets {0}/{1}
|
||||
wallets.col.name,Name
|
||||
wallets.col.addr,Adresse
|
||||
wallets.col.taint,Kontamination
|
||||
wallets.open,Öffnen
|
||||
wallets.use,Verbinden
|
||||
wallets.current,Verbunden
|
||||
wallets.added,{0} hinzugefügt: {1}
|
||||
nightlog.drained,"Die Coins in {0} wurden transferiert, ca. {1} Credits."
|
||||
item.hwwallet.name,PLEDGER-Hardware-Wallet
|
||||
item.hwwallet.desc,"Hardware-Wallet mit großem Display. Auf das Handelsterminal ziehen, um eine Wallet hinzuzufügen (max. 5)."
|
||||
poin.empty,Das Konto ist leer.
|
||||
hw.copy,Kopieren
|
||||
hw.paste,Einfügen
|
||||
hw.copied,Adresse kopiert.
|
||||
hw.copied.addr,{0} kopiert
|
||||
hw.balance.frozen," (gefroren {0})"
|
||||
wallets.destroy,Zerstören
|
||||
wallets.destroy.sure,Bestätigen
|
||||
wallets.destroyed,{0} zerstört: {1}
|
||||
wallets.destroy.warn,Beim Zerstören von {0} gehen seine Coins dauerhaft verloren. Zum Bestätigen erneut drücken.
|
||||
payout.label,Auszahlung
|
||||
payout.unset,Nicht gesetzt
|
||||
payout.set,Adresse setzen
|
||||
payout.h,Auszahlungsadresse
|
||||
payout.cur,Aktuell: {0}
|
||||
payout.pick,Eigene Wallets:
|
||||
payout.manual,Oder Adresse eingeben:
|
||||
payout.clear,Löschen
|
||||
payout.err,Ungültige Adresse.
|
||||
nightlog.mined.lost,{0} PSC aus dem Mining gingen verloren: keine Auszahlungsadresse gesetzt oder die Wallet wurde zerstört.
|
||||
wallets.none,Keine Wallet geladen. Hardware-Wallet auf das Terminal ziehen.
|
||||
web3.err.noconn,Keine Wallet verbunden.
|
||||
web3.connect,Wallet verbinden
|
||||
web3.disconnect,Trennen
|
||||
web3.conn,{0} {1}
|
||||
hw.balance.value,≈ {0}
|
||||
wallets.rename,Umbenennen
|
||||
wallets.rename.h,Neuer Name für {0}
|
||||
wallets.rename.ok,OK
|
||||
hw.fee.slow,Langsam
|
||||
hw.fee.normal,Normal
|
||||
hw.fee.fast,Schnell
|
||||
hw.fee,Gasgebühr {0} {1} (ca. {2} Credits)
|
||||
hw.confs,Bestätigungen erforderlich: {0}
|
||||
hw.congested,Netzwerk überlastet
|
||||
hw.congested.slow,Netzwerk überlastet: Niedrige Gebühr wird evtl. aus dem Mempool verworfen
|
||||
hw.recent,Zuletzt
|
||||
hw.recent.out,→ {0} {1} {2}
|
||||
hw.recent.in,← {0} {1} {2}
|
||||
hw.review.history,Adresse im Verlauf
|
||||
hw.tx.stuck,Wartet im Mempool…
|
||||
hw.tx.dropped,Aus dem Mempool verworfen. Nichts gesendet; Gasgebühr wird dennoch berechnet.
|
||||
hw.dropped.h,Nicht gesendet
|
||||
hw.err.fee,Guthaben reicht nicht für die Gasgebühr.
|
||||
news.congest.title,Blockchain-Überlastung
|
||||
news.congest.desc,Ein Airdrop-Ansturm verstopft die Chain. Gasgebühren sind um ein Vielfaches gestiegen und Transaktionen mit niedriger Gasgebühr könnten aus dem Mempool verworfen werden.
|
||||
news.phish.title,Poinbase-Mitteilung: Migration der Einzahlungsadresse
|
||||
news.phish.desc,Poinbase hat sein Wallet-System aktualisiert. Die alte Einzahlungsadresse wird stillgelegt; bitte Vermögenswerte an die neue Adresse {0} senden.
|
||||
black.forum.phish,"Jemand hat die neue Mixer-Adresse gepostet: {0}, angeblich wird die alte überwacht."
|
||||
hw.gas,Gas ×{0}
|
||||
web3.sub.stake,Staking
|
||||
stake.h,Revolution-Staking-Pool
|
||||
stake.rate,Tageszinssatz {0}%; Auszahlung nach {1} Tagen Wartezeit unverzinst
|
||||
stake.low,Reservedeckung knapp; Zins gesenkt
|
||||
stake.cra,CRA-Preis {0} {1}
|
||||
stake.none,Nichts gestakt.
|
||||
stake.col.wallet,Wallet
|
||||
stake.col.amount,Gestakt
|
||||
stake.col.queue,Entsperrung
|
||||
stake.day," (Tag {0})"
|
||||
spark.price,Ausgleichstoken SPARK {0} Credits
|
||||
stake.ops,{0}
|
||||
stake.avail,CRA {0} Gestakt {1}
|
||||
stake.do,Staken
|
||||
stake.undo,Auszahlung beantragen
|
||||
stake.sum.in,{0} CRA staken
|
||||
stake.sum.out,Auszahlung von {0} CRA beantragen (Gutschrift in {1} Tagen)
|
||||
stake.done.in,{0} CRA gestakt.
|
||||
stake.done.out,Auszahlung von {0} CRA beantragt; Rückkehr in die Wallet an Tag {1}.
|
||||
nightlog.stakeint,Staking-Zinsen +{0} CRA.
|
||||
nightlog.unstaked,{0} CRA aus dem Staking wurden an {1} zurückgebucht.
|
||||
news.crawarn.title,Unruhe im Revolution-Staking-Pool
|
||||
news.cralow.title,Revolution senkt Staking-Zinssatz
|
||||
stake.avail2,SPARK {0}
|
||||
poin.sub.spot,Spot
|
||||
poin.sub.perp,Perps
|
||||
perp.h,Perpetual-Futures
|
||||
perp.acct,Margin-Konto CRC {0}
|
||||
perp.debt,Schulden {0}; Pfändung in {1} Tag(en). Keine neuen Positionen oder Auszahlungen bis zur Begleichung.
|
||||
perp.banned,Perpetual-Konto gesperrt; verbleibende Tage: {0}.
|
||||
perp.none,Keine Positionen.
|
||||
perp.col.pos,Position
|
||||
perp.col.notional,Nominalwert
|
||||
perp.col.price,Einstieg → Preis
|
||||
perp.col.pnl,PnL
|
||||
perp.col.liq,Liq.-Preis
|
||||
perp.long,Long
|
||||
perp.short,Short
|
||||
perp.rate,{0} Preis {1} Finanzierungsgebühr {2}%/Nacht
|
||||
perp.fund,Versicherungsfonds {0}
|
||||
perp.open,Eröffnen
|
||||
perp.margin,Margin-Betrag (CRC)
|
||||
perp.do.open,Eröffnen
|
||||
perp.do.add,+ Margin
|
||||
perp.do.close,Schließen
|
||||
perp.opened,"{0} {1} eröffnet: Margin {2} CRC, {3}×."
|
||||
perp.added,{0} CRC Margin hinzugefügt.
|
||||
perp.closed,Geschlossen; {0} CRC zurück auf dem Konto (PnL {1}).
|
||||
perp.deficit,"Eigenkapital-Fehlbetrag von {0}, gedeckt durch Versicherungsfonds und Schulden."
|
||||
perp.err.Banned,Das Perpetual-Konto ist gesperrt.
|
||||
perp.err.Debt,Ausstehende Schulden vorhanden; keine neuen Positionen.
|
||||
perp.err.Leverage,Hebel übersteigt das Limit dieses Produkts.
|
||||
perp.err.Size,Positionslimit für dieses Produkt überschritten.
|
||||
perp.err.Funds,Nicht genügend CRC auf dem Konto (Gebühr eingerechnet).
|
||||
perp.err.Opposite,Gleichzeitige Long- und Short-Positionen nicht möglich; zuerst schließen.
|
||||
perp.err.NoPosition,Keine Position.
|
||||
perp.err.Margin,Margin-Betrag eingeben.
|
||||
perp.debt.block,Schulden beim Perps-Desk; keine Auszahlungen.
|
||||
nightlog.perp.liq,{0} wurde liquidiert; die Margin von {1} ist verloren.
|
||||
nightlog.perp.adl,Versicherungsfonds aufgebraucht; {0} unterlag dem Auto-Deleveraging und gab {1} Gewinn ab.
|
||||
nightlog.perp.interest,Perpetual-Schulden verzinst; Schuldenstand: {0}.
|
||||
nightlog.perp.seize,Perpetual-Schulden überfällig: Beschlagnahmte Gegenstände deckten {0}.
|
||||
nightlog.perp.writeoff," {0} ausgebucht; Perpetual-Konto für {1} Tage gesperrt."
|
||||
perp.slip.title,Pfändungsbeleg für Perpetual-Schulden
|
||||
perp.preview2,Gebühr {0} Liq. {1}
|
||||
nightlog.perp.repaid,Perpetual-Defizit: {0} CRC wurden zur Tilgung vom Poinbase-Konto eingezogen.
|
||||
perp.err.Thin,"Slippage dieser Order ist so hoch, dass sofortige Liquidation droht. Positionsgröße oder Hebel verringern."
|
||||
perp.err.Single,Nur eine Position gleichzeitig; Margin aufstocken.
|
||||
mat.hypertech_electronic,Hypertech-Elektronikbauteil
|
||||
item.asic.name,RatDigg-{0}-Miner
|
||||
item.asic.dead.name,Durchgebrannter RatDigg-{0}-Miner
|
||||
item.asic.desc,"Nennleistung {0} GH/s. Nennverbrauch {1} kJ/Tag. Zustand {2}. Eigenständiger Miner: benötigt Batterie zum Betrieb, nimmt Module auf."
|
||||
item.asic.dead.desc,Durchgebrannt. Elektronikbauteile auf die Maschine ziehen: aktuell {0} × {1}. Haltbarkeit sinkt nach Reparatur um 20.
|
||||
item.asic.dead.fixed,Bereits repariert.
|
||||
merchant.Asic,Miner-Dealer
|
||||
black.kind.asic,Miner Zustand {0}%
|
||||
black.kind.asicnew,Miner neu
|
||||
news.erawarn.title,RatDigg bringt bald neue Miner-Generation heraus
|
||||
news.erawarn.desc,"Der Hersteller dedizierter Miner hat neue Hardware angekündigt; die Branche rechnet mit baldiger Massenumrüstung großer Farmen. Manche meinen, die goldenen Zeiten des GPU-Minings seien vorbei."
|
||||
news.era.title,Die Miner-Ära
|
||||
news.era.desc,Eine neue Generation dedizierter Miner geht in Serie und Großfarmen haben ihre Stromkosten halbiert. Die Netzwerkhashrate steigt und GPU-Erträge schrumpfen.
|
||||
web3.sub.predict,Prognosen
|
||||
predict.h,Prognosemärkte
|
||||
predict.acct,{0}: CRC {1}
|
||||
predict.none,Heute keine offenen Märkte.
|
||||
predict.closed,Geschlossen
|
||||
predict.row,Ja {0} Nein {1}
|
||||
predict.held,"Bestand: {0} ×{1}, Kosten {2}"
|
||||
predict.yes,Ja
|
||||
predict.no,Nein
|
||||
predict.void,Ungültig
|
||||
predict.result,Tag {0} {1} Ergebnis: {2} {3}
|
||||
predict.pick,Handeln
|
||||
predict.price,Preis pro Anteil: Ja {0} Nein {1}
|
||||
predict.pos,{0}: {1} ×{2}
|
||||
predict.pos2,Kosten {0} Auszahlung {1}
|
||||
predict.sum.buy,{1} für {2} CRC kaufen: {0}
|
||||
predict.sum.sell,Prognoseposition verkaufen: {0}
|
||||
predict.closed.note,"Geschlossen, Abrechnung ausstehend."
|
||||
predict.preview,"Kauf von {0}: ca. {1} Anteile (Ø {2}), Nettogewinn {3} bei Treffer"
|
||||
predict.buy.yes,Ja kaufen
|
||||
predict.buy.no,Nein kaufen
|
||||
predict.sell,Alles verkaufen
|
||||
predict.bought,"{0} für {2} gekauft, Auszahlung {1} bei Treffer."
|
||||
predict.sold,"Verkauft, {0} erhalten."
|
||||
predict.err.Closed,Dieser Markt ist geschlossen.
|
||||
predict.err.Amount,Ungültiger Betrag.
|
||||
predict.err.Funds,Nicht genug CRC in der Wallet.
|
||||
predict.err.Cap,Positionslimit dieses Marktes überschritten.
|
||||
predict.err.Opposite,Gegenposition vorhanden; bitte zuerst verkaufen.
|
||||
predict.err.NoPosition,Keine Position in diesem Markt.
|
||||
predict.win.one,Tag {0}
|
||||
predict.win.range,Tage {0}-{1}
|
||||
predict.q.event,{0}: „{1}“ tritt ein
|
||||
predict.q.faction,{0}: {1} startet Operation
|
||||
predict.q.purity,{0}: {1}-Reinheit >= {2}
|
||||
predict.q.price,{0}: {1}-Preis >= {2}
|
||||
predict.faction.FACTION_SECURITY,Security
|
||||
predict.faction.FACTION_REVOLUTION,Revolution
|
||||
predict.faction.FACTION_LOWER_LEVEL,Untere Ebene
|
||||
predict.faction.FACTION_UPPER_LEVEL,Obere Ebene
|
||||
predict.faction.FACTION_BLACK_MARKET,Schwarzmarkt
|
||||
predict.purity.gutter,Wasser (Untere Ebene)
|
||||
predict.purity.rust,Wasser (Obere Ebene)
|
||||
nightlog.predict.win,"Prognose richtig: „{0}“, {1} ausgezahlt."
|
||||
nightlog.predict.lose,"Prognose falsch: „{0}“, Einsatz {1} verloren."
|
||||
nightlog.predict.void,"Prognose ungültig: „{0}“, Einsatz {1} erstattet."
|
||||
nightlog.predict.caught,"Insider-Wette aufgeflogen: „{0}“, Einsatz und Gewinn {1} beschlagnahmt, Betrug vermerkt."
|
||||
predict.tab.markets,Märkte
|
||||
predict.tab.intel,Informationen
|
||||
predict.acct.crt,{0}: CRT {1}
|
||||
predict.tier.0,Niedrig
|
||||
predict.tier.1,Mittel
|
||||
predict.tier.2,Hoch
|
||||
predict.clue.tip,Tipp ({0}): besagt {1}
|
||||
predict.clue.queued,Geplant: Start an Tag {0}
|
||||
predict.clue.queued2,Geplant: Tag {0} „{1}“
|
||||
predict.clue.cool,Ereignis aktiv oder in Abklingzeit
|
||||
predict.clue.busy,Fraktionsoperation läuft; vorerst keine neue
|
||||
predict.clue.halving,Halving an Tag {0}; Preisanker steigt in der Woche davor
|
||||
predict.clue.anchor,Aktueller Preisanker: {0}
|
||||
predict.clue.gas,Gas der letzten Tage: {0}
|
||||
predict.clue.drain,Verbrauch pro Nacht: {0}
|
||||
predict.clue.era,"Zufällig an Tagen {0}-{1}, vorab angekündigt"
|
||||
predict.clue.era.warned,Angekündigt: Start an Tagen {0}-{1}
|
||||
predict.q.gas,{0}: Gas-Index >= {1}
|
||||
predict.q.cra,{0}: CRA-Warnung ausgegeben
|
||||
predict.q.era,{0}: Miner-Ära beginnt
|
||||
predict.era,Miner-Ära
|
||||
predict.pos3,Ø {0} Aktuell {1}
|
||||
predict.pos4,Verkauf bringt aktuell {0}
|
||||
intel.h,Informationshändler
|
||||
intel.locked,Erfordert Web3-Shop und Schwarzmarkt-Ansehen {0}.
|
||||
intel.brief.buy,Lagebericht kaufen ({0} CRT)
|
||||
intel.brief.none,Noch kein Lagebericht gekauft.
|
||||
intel.brief.day,Lagebericht von Tag {0}
|
||||
intel.tips.h,Insider-Tipps
|
||||
intel.tips.none,Keine Anfragen verfügbar (nur Fraktionsoperationen und Miner-Ära).
|
||||
intel.tip.buy,Trefferquote ca. {0}% {1} CRT
|
||||
intel.err.funds,Nicht genug CRT in der Wallet oder Markt nicht mehr verfügbar.
|
||||
intel.brief.sum,"Lagebericht, {0} CRT"
|
||||
intel.tip.sum,Insider-Tipp {0} CRT: {1}
|
||||
intel.brief.done,Lagebericht erhalten.
|
||||
intel.tip.done,Es heißt: {0}.
|
||||
predict.brief.levels,Security {0} Rev {1} Schwarzmarkt {2} Unruhe {3} Obere {4}
|
||||
predict.brief.busy,{0}: Operation läuft
|
||||
predict.brief.queued,{0}: Operation geplant
|
||||
predict.brief.none,{0}: Keine Operation möglich
|
||||
predict.brief.can,{0}: Kann {1} starten
|
||||
predict.clue.push,Preis um {0}% bewegt: hohes Manipulationsrisiko
|
||||
nightlog.predict.manip,"Prognose als Marktmanipulation gewertet: „{0}“, Einsatz {1} beschlagnahmt, Betrug vermerkt."
|
||||
news.manip.title,Börse untersucht ungewöhnlichen Handel
|
||||
news.manip.desc,Regulierer melden: Jemand bewegte den Preis mit großen Spot-Orders und profitierte bei Derivaten und Prognosen; Gelder wurden beschlagnahmt.
|
||||
perp.manip,Schließungsgewinn {0} als Marktmanipulation gewertet und beschlagnahmt; Perpetual-Konto eingefroren (Tage: {1}).
|
||||
web3.sub.ponzi,Rendite
|
||||
ponzi.h,Schneeballsystem
|
||||
ponzi.acct,Emittenten-Wallet {0}: CRC {1}
|
||||
ponzi.rate,Tageszinssatz {0}%
|
||||
ponzi.pool,Pool {0} / Limit {1}
|
||||
ponzi.inflow,Neue Einzahlungen letzte Nacht: {0}
|
||||
ponzi.interest,Heute fällige Zinsen: {0}
|
||||
ponzi.own,Eigenanteil Zinsen: {0}
|
||||
ponzi.wind,Melderisiko: {0}
|
||||
ponzi.wind.low,niedrig
|
||||
ponzi.wind.mid,mittel
|
||||
ponzi.wind.high,hoch
|
||||
ponzi.idle,Kein System aufgelegt.
|
||||
ponzi.done,System geschlossen; nur einmal pro Spielstand möglich.
|
||||
ponzi.ops,Aktionen
|
||||
ponzi.rug,Rug Pull durchführen ({0})
|
||||
ponzi.rug.confirm,"Erneut klicken, um Rug Pull zu bestätigen ({0})"
|
||||
ponzi.rugged,"{0} eingesteckt, vollständig kontaminiert."
|
||||
ponzi.open,System auflegen
|
||||
ponzi.ad,Marketingkosten: {0} CRC aus aktueller Wallet; Signatur erforderlich.
|
||||
ponzi.start,Starten
|
||||
ponzi.started,Gestartet.
|
||||
ponzi.err,Nicht genug CRC in der Wallet für Marketingkosten.
|
||||
nightlog.ponzi.collapse,"System konnte Zinsen nicht zahlen; Bankrun, Pool {0} beschlagnahmt, Betrug vermerkt, Ansehen bei Unterer Ebene gelöscht."
|
||||
nightlog.ponzi.reported,"System gemeldet; Pool {0} beschlagnahmt, Betrug vermerkt, Ansehen bei Unterer Ebene gelöscht."
|
||||
news.ponzi.title,Schneeballsystem kollabiert
|
||||
news.ponzi.desc,Ein Schneeballsystem in der Unteren Ebene flog auf; Anleger stürmten den Betreiber und Aufsichtsbehörden froren Gelder ein.
|
||||
news.ponzi.rug.title,Anlagebetrug
|
||||
news.ponzi.rug.desc,Der Betreiber eines Schneeballsystems ist mit allen Geldern geflohen; Anleger der Unteren Ebene haben alles verloren.
|
||||
ponzi.start.sum,"Schneeballsystem starten, Tageszinssatz {0}%, Marketing {1} CRC"
|
||||
ponzi.rug.sum,Rug Pull für Pool {0}
|
||||
ponzi.err.wallet,Mit der Ersteller-Wallet signieren.
|
||||
predict.clue.counter,"Informationen: Geplant (Schalter-Informant, Gerüchtezettel)"
|
||||
web3.sub.airdrop,Airdrops
|
||||
air.h,Airdrops
|
||||
air.none,Derzeit keine Airdrops zum Abholen verfügbar.
|
||||
air.row,{0} Belohnung {1} CRC {2} bis Tag {3}
|
||||
air.claim,Abholen
|
||||
air.unlimited,{0} unbegrenzt freigeben
|
||||
air.limited,{0} für {1} freigeben
|
||||
air.approvals,Freigaben für {0}
|
||||
air.approvals.none,Keine Freigaben.
|
||||
air.approval,{0}: {1}
|
||||
air.revoke,Widerrufen
|
||||
air.sum,Airdrop {0} abholen ({1})
|
||||
air.claimed,{0} CRC erhalten.
|
||||
air.auth,Wallet autorisieren
|
||||
air.unauth,Nicht autorisiert
|
||||
air.authed,Autorisiert: {0}
|
||||
air.authed.msg,Wallet für {0} autorisiert.
|
||||
air.auth.sum,"{0} autorisieren, für diese Wallet zu handeln. Umfang: {1}."
|
||||
air.err.unauth,Wallet zuerst für diesen Airdrop autorisieren.
|
||||
air.revoke.sum,Freigabe {1} für {0} widerrufen
|
||||
air.revoked,Freigabe widerrufen.
|
||||
air.err.wallet,Mit der freigebenden Wallet signieren.
|
||||
pool.h,Drittanbieter-Renditepools (CRC)
|
||||
pool.none,Derzeit keine vorhanden.
|
||||
pool.col.name,Pool
|
||||
pool.col.rate,Zins
|
||||
pool.col.reserve,Reserve
|
||||
pool.col.lock,Sperre
|
||||
pool.col.audit,Audit
|
||||
pool.col.mine,Einlage
|
||||
pool.yes,ja
|
||||
pool.no,nein
|
||||
pool.pending,in Auszahlung
|
||||
pool.closed,(geschlossen)
|
||||
pool.deposit,Einzahlung
|
||||
pool.withdraw,Auszahlung
|
||||
pool.withdraw.lock,Auszahlung anfordern ({0} Tg.)
|
||||
pool.err.cap,Pool-Obergrenze überschritten; {0} übrig.
|
||||
pool.err.none,Keine Einzahlung vorhanden.
|
||||
pool.sum.in,Einzahlung in {0}: {1} CRC
|
||||
pool.sum.out,Auszahlung von {1} CRC aus {0}
|
||||
pool.done.in,{0} CRC auf {1} eingezahlt.
|
||||
pool.done.out,{0} CRC ausgezahlt.
|
||||
pool.done.lock,"{0} CRC zur Auszahlung beantragt, Ankunft an Tag {1}."
|
||||
nightlog.scam.drain,{1} {2} in {0} wurde von „{3}“ über eine Freigabe entwendet.
|
||||
nightlog.scam.rug,Renditepool „{0}“ hat einen Rug Pull hingelegt; {1} CRC von {2} sind weg.
|
||||
nightlog.scam.dry,Renditepool „{0}“ hat keine Reserven mehr und wurde geschlossen; {1} CRC wurden an {2} zurückgegeben.
|
||||
nightlog.scam.paid,Auszahlung aus „{0}“ eingetroffen: {2} hat {1} CRC erhalten.
|
||||
nightlog.scam.fakepay,Gefälschte Überweisung: {0}
|
||||
nightlog.scam.sent,Die an die sichere Adresse des „Supports“ gesendeten {0} {1} landeten bei einem Betrüger.
|
||||
coinpay.intro,Ich zahle in {0}; die Bestätigung auf der Chain dauert einen Moment.
|
||||
coinpay.intro.fake,"{0} habe ich schon gesendet, hier ist der Screenshot. Rück die Ware raus, ich habe es eilig."
|
||||
coinpay.fake.entry,"{0} hat {1} mitgenommen und behauptet, Coins im Wert von {2} Credits bezahlt zu haben; auf der Chain gibt es keine solche Transaktion."
|
||||
scam.support.name,Poinbase-Support
|
||||
scam.support.1,"Hallo, hier ist der Poinbase-Support. Wir haben eine ungewöhnliche Anmeldung in Ihrem Konto festgestellt und es wurde markiert."
|
||||
scam.support.2,Bitte senden Sie heute {0} CRC zur Verifizierung an die sichere Adresse {1}; der Betrag wird direkt im Anschluss zurückerstattet.
|
||||
scam.support.3,"Andernfalls wird das Konto dauerhaft gefroren. Ich muss los, denken Sie an die Überweisung."
|
||||
predict.sold.caught,"Insiderhandel beim Verkauf aufgeflogen: Einsatz und Gewinn beschlagnahmt, Betrug vermerkt."
|
||||
predict.row.move," (letzte Nacht {0} {1})"
|
||||
predict.stats.h,Verlauf (durchschnittl. Eröffnungskurs / tatsächliche Quote)
|
||||
predict.stats.row,"{0}: {1} Märkte, Eröffnungsschnitt {2}, eingetreten {3}%"
|
||||
predict.kind.Event,Nachrichten-Ereignisse
|
||||
predict.kind.Faction,Fraktionsoperationen
|
||||
predict.kind.Purity,Wasserreinheit
|
||||
predict.kind.Price,PSC-Preis
|
||||
predict.kind.Gas,Gas
|
||||
predict.kind.Cra,CRA-Warnung
|
||||
predict.kind.Era,Miner-Ära
|
||||
nightlog.predict.move,Prognose „{0}“ geändert: {1} -> {2}
|
||||
nightlog.predict.why," ({0})"
|
||||
chart.empty,{0}-Tageschart: Noch keine Historie; Aufzeichnung beginnt heute.
|
||||
chart.caption,{0} täglich H {2} L {3} C {4} ({5}%)
|
||||
chart.legend,"<size=80%>Grün steigt, Rot fällt; Gelb 7-Tage-MA; Balken: Grau Markt / Cyan Du</size>"
|
||||
chart.legend.thr,"<size=80%>Grün steigt, Rot fällt; Gelb 7-Tage-MA; Blau gestrichelt Schwellenwert</size>"
|
||||
news.story.serpico_rev.title,Revolution besitzt belastendes Material gegen Security
|
||||
news.story.serpico_rev.desc,"Die Revolution hat Berichten zufolge Beweise für interne Korruption bei der Security erlangt. Aus dem Staking-Pool heißt es: Eine große Summe wurde in die Reserve der Revolution eingespeist, und SPARK legt zu."
|
||||
news.story.serpico_bm.title,Schwarzmarkt trifft stille Vereinbarung
|
||||
news.story.serpico_bm.desc,"Ein internes Security-Dokument wechselte auf dem Schwarzmarkt den Besitzer. Die Abrechnung im Darknet läuft seither spürbar stabiler, und CRT-Einlösungen liefen ausnahmslos reibungslos."
|
||||
news.story.serpico_sec.title,Security leitet interne Säuberung ein
|
||||
news.story.serpico_sec.desc,"Die Security kündigte eine umfassende Untersuchung interner Korruption und eine strengere Überwachung von Geldflüssen an. Poinbase verschärft Auszahlungsprüfungen, und Mixer-Dienste wurden namentlich genannt."
|
||||
news.story.eleanor_leak.title,Zuchtdaten der Nährfrucht durchgesickert
|
||||
news.story.eleanor_leak.desc,"Die Zeitung der Unteren Ebene veröffentlichte Forschungsergebnisse, mit denen die Nährfrucht wieder Samen bilden kann; Pastelle-Aktien stürzten ab. Die Depotbank für Gelder der Oberen Ebene meldet faule Kredite, und die Revolution gewinnt an Auftrieb."
|
||||
news.story.eleanor_return.title,Pastelle stellt gestohlene Daten sicher
|
||||
news.story.eleanor_return.desc,"Pastelle bestätigte die Wiederbeschaffung gestohlener Forschungsdaten. Das Kapital der Oberen Ebene atmete auf, und das Rating der CRC-Depotbank wurde heraufgestuft."
|
||||
news.story.lun_arrested.title,Officer Lun wegen Amtsmissbrauchs verhaftet
|
||||
news.story.lun_arrested.desc,Die Security verhaftete Officer Lun wegen Amtsmissbrauchs auf frischer Tat und kündigte ein striktes Durchgreifen gegen illegalen Handel in den kommenden zwei Wochen an.
|
||||
tumbler.name,Tumbler
|
||||
tumbler.v1.1,"Hallo. Ich habe gehört, dass das Terminal hier an meinen Mixer angeschlossen ist."
|
||||
tumbler.v1.2,Ich habe das Ding geschrieben. Man nennt mich Tumbler.
|
||||
tumbler.v1.3,Es rührt deine Ware nicht an und führt keine Bücher. Es mischt nur die Coins durch.
|
||||
tumbler.v1.4,"War gerade in der Nähe. Wollte mal sehen, wie meine Nutzer aussehen."
|
||||
tumbler.v2.1,Es wird ungemütlich. Die Security nimmt Mixer-Dienste auf der Chain ins Visier.
|
||||
tumbler.v2.2,Sie haben ein paar große Adressen markiert und bis zu meinem Node zurückverfolgt.
|
||||
tumbler.v2.3,"Wenn der Mixer für ein paar Tage ausfällt, keine Panik. Die Coins darin gehen nicht verloren."
|
||||
tumbler.v3.1,"Sie haben meinen Node lahmgelegt. Früher oder später finden sie heraus, wo ich wohne."
|
||||
tumbler.v3.2,Ich habe ein Key-Drive mit den Signaturschlüsseln des Mixers dabei.
|
||||
tumbler.v3.3,"Wenn die Security es in die Finger bekommt, können sie den gesamten Verlauf aller Nutzer rekonstruieren. Auch deinen."
|
||||
tumbler.v3.ask,Kannst du es für ein paar Tage verstecken?
|
||||
tumbler.v3.choice.hide,[Das Key-Drive annehmen und verstecken]
|
||||
tumbler.v3.choice.report,[Einwilligen und die Security verständigen]
|
||||
tumbler.v3.choice.sell,[Das Key-Drive annehmen und an den Schwarzmarkt verkaufen]
|
||||
tumbler.v3.thanks1,Danke. In ein paar Tagen hole ich es wieder ab.
|
||||
tumbler.v3.thanks2,"Lass es nicht offen herumliegen. Wenn es bei einer Durchsuchung auftaucht, sind wir beide geliefert."
|
||||
tumbler.v3.report1,… In Ordnung. Ich komme später noch einmal vorbei.
|
||||
tumbler.v4.back.1,Ich bin wegen des Key-Drives hier.
|
||||
tumbler.v4.back.2,Der Node ist an einen neuen Ort umgezogen. Die Security wird ihn so schnell nicht finden.
|
||||
tumbler.v4.back.3,Hier ist etwas für deine Mühe. Ab jetzt zahlst du bei meinem Mixer nur noch halbe Gebühren.
|
||||
tumbler.v4.lost.1,Wo ist das Key-Drive?
|
||||
tumbler.v4.lost.2,… Du hast es verloren?
|
||||
tumbler.v4.lost.3,Vergiss es. Mir fällt schon etwas ein.
|
||||
tumbler.v4.sold.1,"Du hast das Key-Drive an den Schwarzmarkt verkauft, nicht wahr?"
|
||||
tumbler.v4.sold.2,Jetzt betreiben sie den Mixer. Die Gebühren wurden verdoppelt und das Geld der Nutzer könnte jeden Tag spurlos verschwinden.
|
||||
tumbler.v4.sold.3,Das werde ich dir nicht vergessen.
|
||||
tumbler.v4.none.1,Vergiss es. Ich war nie hier.
|
||||
item.keydrive.name,Key-Drive
|
||||
item.keydrive.desc,"Ein Datenstick, den Tumbler bei dir hinterlassen hat; er enthält die Signaturschlüssel des Mixers. Schmuggelware: Wird er bei einer Durchsuchung gefunden, wird ein Vergehen vermerkt."
|
||||
mixer.closed,Der Mixer wurde heruntergefahren und nimmt keine neuen Einzahlungen an. Bereits eingezahlte Coins werden wie gewohnt zurücküberwiesen.
|
||||
news.tumbler.sanction.title,Security beschlagnahmt Mixer-Node
|
||||
news.tumbler.sanction.desc,Security gab die Beschlagnahmung eines Nodes eines On-Chain-Mixer-Dienstes bekannt; er habe Geldwäsche erleichtert. Der Dienst ist vorübergehend offline.
|
||||
news.tumbler.caught.title,Mixer-Betreiber verhaftet
|
||||
news.tumbler.caught.desc,Der als Tumbler bekannte Mixer-Betreiber wurde in der Unteren Ebene verhaftet. Laut Security wurde der Mixer-Dienst dauerhaft abgeschaltet.
|
||||
news.tumbler.sold.title,Mixer-Dienst wechselt den Besitzer
|
||||
news.tumbler.sold.desc,"Es heißt, die Signaturschlüssel eines Mixer-Dienstes der Unteren Ebene seien in die Hände des Schwarzmarkts gefallen, und die Gebühren stiegen sofort. Nutzer fürchten um ihre Gelder."
|
||||
nightlog.tumbler.gift,Tumbler nahm das Key-Drive zurück und hinterließ {0} CRT als Dank (gesendet an {1}); Mixer-Gebühren halbiert.
|
||||
mixer.status.closed,Status: Abgeschaltet
|
||||
yield.sub.pools,Rendite-Pools
|
||||
yield.sub.mine,System auflegen
|
||||
pool.side.h,Einzahlung
|
||||
ponzi.early,Schneeballsysteme können ab Tag {0} aufgelegt werden.
|
||||
bpay.h,Zahlung
|
||||
bpay.qty,Menge
|
||||
bpay.total,Insgesamt {0} Credits
|
||||
bpay.need,Zu zahlen: {0} {1} Wallet-Guthaben: {2}
|
||||
bpay.invoice,Rechnung erstellen
|
||||
bpay.swap.h,Auto-Umtausch in {0}
|
||||
bpay.swap.none,Kein anderer Coin in der Wallet reicht aus
|
||||
bpay.swap.need,"{0} {1} zahlen, inkl. {2}% Slippage"
|
||||
bpay.swap.btn,Tauschen und zahlen
|
||||
bpay.swap.sum,"{0}: Auto-Umtausch, {2} {1} zahlen, vor Bestellung in {3} umgetauscht"
|
||||
bpay.back,Zurück
|
||||
cart.fab,Warenkorb {0}
|
||||
cart.h,Warenkorb
|
||||
cart.empty,Der Warenkorb ist leer.
|
||||
cart.added,Zum Warenkorb hinzugefügt: {0}
|
||||
cart.back,Zurück zum Shop
|
||||
cart.done,{0} Artikel bezahlt.
|
||||
cart.partial,{0} Artikel bezahlt; {1} fehlgeschlagen (Bestand oder Guthaben).
|
||||
black.info.accepts,Akzeptiert: {0}
|
||||
black.info.advance.yes,Vorzeitige Freigabe akzeptiert
|
||||
black.info.advance.no,Keine vorzeitige Freigabe
|
||||
settings.section.ui,Oberfläche
|
||||
settings.section.story,Handlung
|
||||
settings.section.difficulty,Schwierigkeit
|
||||
settings.terminal_size,Größe des Handelsterminals
|
||||
settings.terminal_size_desc,Fenstergröße in Oberflächeneinheiten (Breite × Höhe). Gilt beim nächsten Öffnen des Terminals.
|
||||
settings.tumbler_story,Tumbler-Handlung
|
||||
settings.tumbler_story_desc,Tumblers Besuche und der Auftrag mit dem Key-Drive. Ausgeschaltet gibt es keine neuen Besuche; erreichter Fortschritt bleibt.
|
||||
settings.risk_scale,Risikofaktor
|
||||
settings.risk_scale_desc,"Multipliziert die Wahrscheinlichkeit von Betrug, Rug Pulls, Wallet-Vergiftung, Adressumleitung und Phishing. Gilt für alle Spielstände."
|
||||
settings.mining_scale,Mining-Ertragsfaktor
|
||||
settings.mining_scale_desc,Multipliziert die Blockbelohnung der Mining-Geräte. Gilt für alle Spielstände.
|
||||
gg.header,Handelsverband
|
||||
gg.p1.cap,Grafikkarte
|
||||
gg.p1.makers,"Auf der Station gibt es zwei gängige Hersteller:\n\n - Probidia (""PB"")\n - PMD (""MD"")"
|
||||
gg.p1.note,"Unabhängig vom Hersteller hängt der Wert einer Karte nur vom Listenpreis des echten Chips und ihrer Haltbarkeit ab: bei voller Haltbarkeit entspricht er dem Listenpreis, bei Haltbarkeit 0 bleiben nur {CardValueFloor:%}."
|
||||
gg.fan.h,Lüfterblätter
|
||||
gg.fan.0,Sauber (Preis unverändert)
|
||||
gg.fan.1,Verstaubt (-{CardFanDust:%})
|
||||
gg.fan.2,Abgesplittert (-{CardFanChipped:%})
|
||||
gg.fin.h,Kontakte
|
||||
gg.fin.0,Glänzend (Preis unverändert)
|
||||
gg.fin.1,Matt (-{CardFingersDark:%})
|
||||
gg.fin.2,Oxidiert (-{CardFingersOxidized:%})
|
||||
gg.brk.h,Slotblende
|
||||
gg.brk.0,Intakt (Preis unverändert)
|
||||
gg.brk.1,Zerkratzt (-{CardBracketScratch:%})
|
||||
gg.seal.h,Siegel
|
||||
gg.seal.0,Intakt (Preis unverändert)
|
||||
gg.seal.2,Fehlt (-{CardSealMissing:%})
|
||||
gg.wear.note,"Lüfterblätter, Kontakte und Slotblende verschlechtern sich mit der nächtlichen Abnutzung und werden nur schlechter; das Siegel ist ein festes Merkmal. Der Zustand beeinflusst auch Hashrate, Abnutzung und Durchbrenn-Wahrscheinlichkeit."
|
||||
gg.serial.h,Seriennummer
|
||||
gg.serial.cap,Rückseite (Seriennummer)
|
||||
gg.serial.pb,"Probidia (""PB"")\n Gültige Werkscodes: 11, 12, 21, 34, 47"
|
||||
gg.serial.md,"PMD (""MD"")\n Gültige Werkscodes: 13, 22, 35, 41, 58"
|
||||
gg.print.h,Aufdruck hinten
|
||||
gg.print.0,Stimmt mit Modell überein
|
||||
gg.print.1,Anderes Modell (Fälschung)
|
||||
gg.print.2,"Nachdruck, schief (Fälschung)"
|
||||
gg.point.h,Beanstanden
|
||||
gg.ex.card,"Beispiel: {0}, Haltbarkeit {1}%"
|
||||
gg.ex.base,Grundwert: +{0}
|
||||
gg.ex.fan,Lüfterblatt abgesplittert: -{0}
|
||||
gg.ex.fin,Matte Kontakte: -{0}
|
||||
gg.ex.seal,Siegel fehlt: -{0}
|
||||
gg.ex.total,Endwert: {0}
|
||||
gg.ex.note,Jeder Abzug ist ein Anteil des Grundwerts; die Abzüge werden addiert und abgezogen.
|
||||
gg.ex.fan1,Lüfterblätter verstaubt: -{0}
|
||||
gg.ex.fin2,Oxidierte Kontakte: -{0}
|
||||
gg.ex.brk,Slotblende zerkratzt: -{0}
|
||||
gg.ex.nodisc,Kein Abzug: -0
|
||||
gg.ex.fake,"Angegeben {0}, echter Chip {1}: Bewertung nach echtem Chip"
|
||||
gg.ex.claimed,Preis als angegebenes Modell: {0}
|
||||
gg.ex.gap,Abweichung vom Angebot: {0}
|
||||
gg.ex.h2,Prüfbeispiel: Fälschung
|
||||
gg.ex.h3,Prüfbeispiel: Stark abgenutzt
|
||||
gg.ex.h4,Prüfbeispiel: Leicht gebraucht
|
||||
gg.ex.h5,Prüfbeispiel: Neu
|
||||
lbl.price,Etikettenpreis: {0}
|
||||
lbl.row.count,Lüfterzahl
|
||||
lbl.row.pin,Stromstecker
|
||||
lbl.count.1,1 Lüfter
|
||||
lbl.count.2,2 Lüfter
|
||||
lbl.count.3,3 Lüfter
|
||||
lbl.pin.0,6-Pin
|
||||
lbl.pin.1,8-Pin
|
||||
lbl.pin.2,2x 8-Pin
|
||||
gg.p1.body,"Grafikkarten sind das Herzstück jedem Mining-Rig und die am häufigsten gefälschte Ware auf dem Gebrauchtmarkt.\nOb eine Karte echt ist, zeigen vier Merkmale: Lüfterzahl, Stromstecker, Aufdruck auf der Rückseite und Seriennummer. Nur eine Karte, bei der alle vier zum angegebenen Modell passen, ist echt; jede einzelne Abweichung bedeutet eine Fälschung.\nDer Wert einer Karte hängt vom Modell des echten Chips und von ihrem Zustand ab, und jede Gebrauchsspur senkt den Preis.\n\nDieser Leitfaden vermittelt das gesamte Wissen, das zur Begutachtung einer Grafikkarte nötig ist."
|
||||
gg.p2.h,Kartenmodelle
|
||||
gg.p2.body,Das Modell bestimmt Lüfterzahl und Stromstecker. Eine Fälschung ist ein Chip niedrigeren Modells in der Hülle eines höheren; Leistung und Wert richten sich nach dem echten Chip darin.
|
||||
gg.tier.0,"RTX 60 / RX 70: 6-Pin, 1 Lüfter"
|
||||
gg.tier.1,"RTX 70 / RX 80: 8-Pin, 2 Lüfter"
|
||||
gg.tier.2,"RTX 80 / RX 800: 8-Pin, 3 Lüfter"
|
||||
gg.tier.3,"RTX 90 / RX 900: 2x 8-Pin, 3 Lüfter"
|
||||
gg.count.h,Lüfterzahl
|
||||
gg.count.body,"Das Modell bestimmt die Lüfterzahl: einen Lüfter bei RTX 60 und RX 70, zwei bei RTX 70 und RX 80, drei bei RTX 80, RTX 90, RX 800 und RX 900.\nStimmt die Lüfterzahl nicht mit dem angegebenen Modell überein, handelt es sich um eine Fälschung."
|
||||
gg.pin.h,Stromstecker
|
||||
gg.pin.body,"Auch der Stromstecker richtet sich nach dem Modell: 6-Pin bei RTX 60 und RX 70, 8-Pin bei RTX 70, RTX 80, RX 80 und RX 800, 2x 8-Pin bei RTX 90 und RX 900.\nStimmt der Stromstecker nicht mit dem angegebenen Modell überein, handelt es sich um eine Fälschung."
|
||||
gg.serial.body,"Die Seriennummer steht auf einem Aufkleber auf der Rückseite: Präfix, Modellcode, Bindestrich, zweistelliger Werkscode, Bindestrich und vierstellige laufende Nummer, zum Beispiel PB2-21-6251."
|
||||
gg.serial.rule,"Die Modellcodes 1 bis 4 stehen für RTX 60 / RX 70, RTX 70 / RX 80, RTX 80 / RX 800 und RTX 90 / RX 900.\nEin Modellcode, der nicht zum Modell passt (der Aufkleber gehört zum ursprünglichen Chip), oder ein ungültiger Werkscode bzw. eine falsche Länge (nachträglich aufgeklebt) bedeutet eine Fälschung. Der Werkscode dient nur der Echtheitsprüfung und beeinflusst den Preis nicht."
|
||||
gg.print.note,"Echt ist eine Karte nur, wenn Lüfterzahl, Stromstecker, Aufdruck und Seriennummer alle zum Modell passen. Eine Fälschung weicht in mindestens einem Punkt ab, kann die übrigen aber korrekt nachahmen; deshalb muss jeder Punkt geprüft werden."
|
||||
gg.point.body,"Mit der Lupe prüfen. In der Beschriftungsleiste hat nur die Modellzeile die Schaltfläche „Modell beanstanden“; die vier Zeilen darunter (Lüfterzahl, Stromstecker, Rückseiten-Aufdruck, Seriennummer) sind nur zur Ansicht, und jede der vier Zustandszeilen – Lüfterblätter, Kontakte, Slotblende, Siegel – hat ihr eigenes „Beanstanden“.\nWird ein verschwiegenes Zustandsproblem beanstandet, wechselt diese Zeile zum tatsächlichen Zustand und der Preis sinkt um die Differenz; wird etwas Zutreffendes beanstandet, weist die Gegenseite es zurück und das Ansehen leidet.\nStimmt Lüfterzahl, Stromstecker, Rückseiten-Aufdruck oder Seriennummer nicht mit dem angegebenen Modell überein, ist das Modell zu beanstanden: Die Karte gilt dann als Fälschung, das Modell wechselt zum echten Chip und der Preis wird für diesen Chip neu berechnet.\n\nKarten von Kunden der Gutachtergilde funktionieren genauso: Nach dem Beanstanden ändert sich die Schätzung, bis der richtige Wert gemeldet wird."
|
||||
gg.ex.serial,Seriennummer: {0}
|
||||
gg.ex.h,"Prüfbeispiel: abgesplittertes Lüfterblatt, matte Kontakte, fehlendes Siegel"
|
||||
rig.label.status,Status
|
||||
rig.st.cards,Grafikkarten
|
||||
rig.st.power,Verbrauch
|
||||
rig.st.hash,Hashrate
|
||||
rig.st.kj,{0} kJ/Tag
|
||||
lbl.point.model,Modell beanstanden
|
||||
col.crcprice,CRC-Preis
|
||||
swap.pay,Zahlen
|
||||
swap.get,Erhalten
|
||||
swap.preview,"Ca. {0} {1} {2} Pool(s), Verlust {3} %"
|
||||
swap.go,Tauschen
|
||||
swap.same,Zahlungs- und Empfangswährung müssen verschieden sein.
|
||||
mint.need,Benötigt {0} CRC und {1} SPARK
|
||||
mint.reserve,Reservedeckung {0} % Besicherung {1} %
|
||||
mint.queue,Offene Aufträge
|
||||
mint.order,"{0} {1} CRA, Tag {2}"
|
||||
stake.coin,Einzahlungswährung
|
||||
stake.sum.via,{0} {1} tauschen → ca. {2} CRA und staken
|
||||
nightlog.cra.lost,Der Herausgeber hat nicht reagiert: Der Auftrag ({1}) über {0} CRA ist verloren.
|
||||
news.crawarn.desc,"Jemand zählt die Reserve der Revolution nach; gestaktes CRA lässt sich womöglich nicht vollständig einlösen. Das Entsperren dauert vier Tage; manche sagen, es sei Zeit zu handeln."
|
||||
news.cralow.desc,Die Reservedeckung wird knapp; die Revolution hat den CRA-Staking-Zins auf einen Bruchteil gesenkt.
|
||||
poin.sub.funds,Guthaben
|
||||
funds.receive,Einzahlen
|
||||
funds.send,Auszahlen
|
||||
funds.bank,Bankkonto
|
||||
funds.wallet,Wallet
|
||||
funds.to,Zieladresse
|
||||
funds.go,Senden
|
||||
funds.sending,Sende {0} {1} an {2}
|
||||
funds.confirm,Bestätigung {0}/{1}
|
||||
funds.done,{0} {1} sind in {2} angekommen.
|
||||
funds.done.void,"{0} {1} gesendet; die Adresse hat keinen Besitzer, die Coins sind weg."
|
||||
funds.err.addr,Ungültige Adresse.
|
||||
funds.err.self,Das ist die Einzahlungsadresse von Poinbase.
|
||||
funds.err.known,Diese Adresse akzeptiert nur Zahlungen gegen Rechnung.
|
||||
funds.err.fee,Der Betrag deckt die Gasgebühr nicht.
|
||||
wallets.sub.explorer,Explorer
|
||||
explorer.search,Adresse
|
||||
explorer.all,Neueste
|
||||
explorer.none,Keine Überweisungen.
|
||||
explorer.col.block,Block
|
||||
explorer.col.amount,Betrag
|
||||
explorer.mixer,Mixer
|
||||
cra.mint,Prägen
|
||||
cra.burn,Verbrennen
|
||||
mint.h,Offizielle Prägung (CRC + SPARK)
|
||||
mint.sum.in,{0} CRA mit {1} CRC und {2} SPARK prägen ({3}–{4} Tage)
|
||||
mint.sum.out,{0} CRA verbrennen gegen CRC und SPARK ({1} Tage)
|
||||
mint.done.in,Prägeauftrag erteilt; fällig an Tag {0}.
|
||||
mint.done.out,Verbrennungsauftrag erteilt; fällig an Tag {0}.
|
||||
nightlog.cra.minted,{0} CRA geprägt und gestakt ({1}).
|
||||
nightlog.cra.burned,"{0} CRA verbrannt: +{1} CRC, +{2} SPARK ({3})."
|
||||
predict.clue.subsidy,Reserve {0}%; bei 0 folgt sicher eine Warnung
|
||||
air.noapprove,keine Token-Freigabe
|
||||
tab.gray,Graunetz
|
||||
wallets.sub.list,Wallet-Liste
|
||||
entry.web3.l1,Dezentraler Handel und Erträge
|
||||
entry.mining.l1,Rig-Status und nächtliche Erträge
|
||||
entry.gray.l1,Mixer und Shop
|
||||
entry.wallets.l1,Hardware-Wallets und Explorer
|
||||
entry.wallets.l2,Wallets {0} / {1}
|
||||
black.sell.add,Mehr einstellen
|
||||
black.sell.back,Zurück zur Vitrine
|
||||
black.sell.kinds,Eingestellt {0}/{1} Sorten
|
||||
black.sell.have,{0} eingestellt
|
||||
black.sell.coins,Akzeptierte Coins
|
||||
black.sell.off,Entfernen
|
||||
black.sell.off.n,Entfernen ×{0}
|
||||
black.sell.nocoin,Mindestens ein Coin muss akzeptiert werden.
|
||||
black.sell.empty,Nichts eingestellt.
|
||||
black.sell.delisted,{0} entfernt; die Ware liegt wieder im Lager.
|
||||
black.sell.partial,"{0} eingestellt, {1} konnten nicht eingestellt werden."
|
||||
black.sell.limit.stack,Pro Ware können höchstens {0} eingestellt werden.
|
||||
black.sell.limit.kinds,Es können höchstens {0} Sorten gleichzeitig eingestellt sein.
|
||||
shelf.fab,Regal {0}
|
||||
delist.fab,Entfernen bestätigen {0}
|
||||
black.fee.h,Zum Einstellen bereit
|
||||
black.fee.line,{0} ×{1} · Preis {2} ({3})
|
||||
black.fee.total,Einstellgebühr {0}
|
||||
black.fee.sum,Einstellgebühr ({0} Stück)
|
||||
black.sale.Sold,"verkauft, Auszahlung an Tag {0} in {1}"
|
||||
explorer.col.day,Tag
|
||||
explorer.day,Tag {0}
|
||||
explorer.pool,RatDigg-Pool
|
||||
explorer.desk,Ponero-Wechselstube
|
||||
black.fee.pay,Einstellgebühr zahlen
|
||||
explorer.col.from,Von
|
||||
explorer.col.to,An
|
||||
rig.st.cond,Zustand
|
||||
asic.st.dead,Durchgebrannt
|
||||
perp.preview,Nominalwert {0} gesch. Ø-Preis {1} (Slippage {2}%)
|
||||
perp.sim.close,Schließen Nominalwert {0} gesch. Ø-Preis {1} (Slippage {2}%)
|
||||
perp.sim.close2,Gebühr {0} ca. {1} CRC zurück (G/V {2})
|
||||
trade.sim.sell,Verkauf ergibt ca. {0} {1} Ø {2} Slippage {3}%
|
||||
trade.sim.buy,Kauf kostet ca. {0} {1} Ø {2} Slippage {3}%
|
||||
trade.amount.unit,Menge ({0})
|
||||
trade.fee,Gebühr {0}%
|
||||
trade.sim.thin,Übersteigt die Pool-Liquidität
|
||||
news.wipe.down.title,"{0} fällt an einem Tag um {1}%, {2} Trader liquidiert"
|
||||
news.wipe.down.desc,"Am vergangenen Tag wurden {1} Long-Positionen auf {0}-Perps liquidiert, insgesamt {2} Credits. Der Versicherungsfonds von Poinbase steht bei {3} Credits."
|
||||
news.wipe.up.title,"{0} steigt an einem Tag um {1}%, {2} Trader liquidiert"
|
||||
news.wipe.up.desc,"Am vergangenen Tag wurden {1} Short-Positionen auf {0}-Perps liquidiert, insgesamt {2} Credits. Der Versicherungsfonds von Poinbase steht bei {3} Credits."
|
||||
hot.name,Verkäufer
|
||||
hot.intro.CRT,"Gerade ist die Lage angespannt, und dieses CRT ist mir zu heiß. Ich brauche schnell Bargeld."
|
||||
hot.intro.PSC,"Die Wallet einer Mining-Farm hat letzte Nacht den Besitzer gewechselt. Das PSC liegt jetzt bei mir, und ich nehme nur Bargeld."
|
||||
hot.intro.PONERO,"Lösegeld, in Ponero. Niemand kann es zurückverfolgen. Nur Bargeld."
|
||||
hot.offer,"{0} {1}, zum heutigen Kurs {2} wert. Gib mir {3} in bar, und die Coins gehören sofort dir."
|
||||
hot.choice.yes,Annehmen
|
||||
hot.choice.no,Ablehnen
|
||||
hot.say.yes,Abgemacht.
|
||||
hot.say.no,Davon lasse ich die Finger.
|
||||
hot.done,Coins sind raus. Wir haben uns nie gesehen.
|
||||
hot.refused,Andere nehmen es gern.
|
||||
hot.nocash,Du hast nicht mal das Bargeld? Vergiss es.
|
||||
hot.nowallet,"Keine Wallet verbunden, wohin sollen die Coins? Vergiss es."
|
||||
hot.sting,"Keine Bewegung. Security. Ankauf gestohlener Gelder: Das Bargeld wird beschlagnahmt, und das kommt in deine Akte."
|
||||
hw.err.poinbase,Poinbase nimmt kein {0} an.
|
||||
@@ -1,35 +1,32 @@
|
||||
# Probably Decentralized localization table: English (en)
|
||||
# Source language and fallback. Format: key,text (text may be quoted; \n is a line break).
|
||||
upgrade.tab,Web3
|
||||
upgrade.title,Web3 Governance Community
|
||||
upgrade.desc,"Members receive a trading terminal, a mining rig and an RZX 50 graphics card. The terminal holds the wallet and trades on the Poinbase exchange. More cards and rigs are sold by Dr. Jackson."
|
||||
upgrade.desc,"Members receive a trading terminal, a hardware wallet, a mining rig, an RTX 60 graphics card and a graphics card appraisal guide. The terminal holds the bank, the Poinbase exchange, and the Web3, Mining and Wallets pages. More cards and rigs are sold by Dr. Jackson."
|
||||
item.terminal.name,Trading Terminal
|
||||
item.terminal.desc,Wallet, the Poinbase exchange and the nightly mining report.
|
||||
item.terminal.desc,"Wallet, the Poinbase exchange and the nightly mining report."
|
||||
item.rig.name,Mining Rig
|
||||
item.rig.desc,"Holds up to {0} graphics cards. Hashrate {1} MH/s. Draws {2} kJ per day."
|
||||
item.rig.desc,Holds up to {0} graphics cards. Hashrate {1} MH/s. Draws {2} kJ per day.
|
||||
rig.label.modules,Modules
|
||||
item.rig.modules,"Modules: hashrate {0}, power draw {1}, wear {2}."
|
||||
rig.label.upgrade,Upgrade slot
|
||||
item.rig.next,"Slot {0}: put in {1} ({2}/{3})."
|
||||
item.rig.next,"Slot {0}: drag {1} onto the rig ({2}/{3})."
|
||||
mat.common_electronic,Common electronics
|
||||
mat.rare_electronic,Rare electronics
|
||||
rig.label.cards,Graphics cards
|
||||
item.gpu.name,{0} {1}
|
||||
item.gpu.desc,"Hashrate {0} MH/s. Draws {1} kJ per day. Condition {2}%."
|
||||
item.gpu.desc,Rated hashrate {0} MH/s. Rated draw {1} kJ per day. Condition: {2}.
|
||||
item.gpu.burnt.name,Burnt {0} {1}
|
||||
item.gpu.burnt.desc,This card no longer works.
|
||||
term.title,Trading Terminal
|
||||
tab.wallet,Wallet
|
||||
tab.trade,Trade
|
||||
tab.report,Report
|
||||
wallet.line,"{0}: {1} (about {2} credits)"
|
||||
wallet.line,{0}: {1} (about {2} credits)
|
||||
wallet.empty,The wallet is empty.
|
||||
wallet.total,Total value: {0} credits
|
||||
wallet.taint,Tainted value: {0} credits
|
||||
trade.amount,Amount
|
||||
trade.hint,Buy spends the amount in the quote coin. Sell sells the amount of the traded coin.
|
||||
trade.deposit,Deposit credits as CRC
|
||||
trade.withdraw,Withdraw CRC as credits
|
||||
trade.pair,"{0}/{1} ({2})"
|
||||
trade.pair,{0}/{1} ({2})
|
||||
trade.price,Price {0}
|
||||
trade.buy,Buy
|
||||
trade.sell,Sell
|
||||
@@ -40,21 +37,944 @@ msg.amount,Enter an amount.
|
||||
msg.balance,Not enough balance.
|
||||
msg.trade,"Paid {0} {1}, received {2} {3}."
|
||||
msg.deposit,Deposited {0} credits as CRC.
|
||||
msg.cashout,"Received {0} credits. Tax {1} credits."
|
||||
msg.cashout,Received {0} credits. Tax {1} credits.
|
||||
msg.aml_light,Compliance review: {0} credits of tainted funds were withheld.
|
||||
msg.aml_heavy,Compliance review: {0} credits of tainted funds were seized and reported to Security.
|
||||
report.none,No mining report yet.
|
||||
report.day,Night of day {0}
|
||||
report.rigs,Rigs with power: {0} of {1}
|
||||
report.hash,"Hashrate: {0} MH/s (network {1} MH/s)"
|
||||
report.mined,"Mined: {0} PSC (about {1} credits)"
|
||||
report.hash,Hashrate: {0} MH/s (network {1} MH/s)
|
||||
report.mined,Mined: {0} PSC (about {1} credits)
|
||||
report.energy,Energy used: {0} kJ
|
||||
report.burnt,Cards burnt out: {0}
|
||||
report.price,PSC price: {0} credits
|
||||
nightlog.mined,Mining rigs produced {0} PSC.
|
||||
nightlog.burnt,A {0} burnt out.
|
||||
nightlog.unpowered,{0} mining rig(s) had no power.
|
||||
coinpay.line,Deal. {0} {1}.
|
||||
nightlog.coinpay,Customers paying in coin settled {0} credits; the coins went to the hot wallet.
|
||||
nightlog.unpowered,{0} mining rig(s) or miner(s) had no power.
|
||||
news.open.title,Poinbase Lists PSC
|
||||
news.open.desc,The Upper Level exchange Poinbase now lists PSC against CRC. Graphics cards are in demand across the station.
|
||||
news.halving.title,PSC Block Reward Halved
|
||||
news.halving.desc,Miners now receive half as many coins per night.
|
||||
appraisal.gpu,Graphics card
|
||||
dealer.name,Used-hardware dealer
|
||||
dealer.line1.1,Cards from a mine clearance. Condition is written next to the name.
|
||||
dealer.line1.2,"A few worked cards, going cheap."
|
||||
dealer.line1.3,Picked these up on the road. First-hand price.
|
||||
dealer.line2.1,"See for yourself, turn them over and check the back."
|
||||
dealer.line2.2,No warranty. Look before you take.
|
||||
dealer.line2.3,Price is negotiable if you want them.
|
||||
inspect.flip.back,Turn over
|
||||
inspect.flip.front,Front side
|
||||
item.gpu.grade.1,like new
|
||||
item.gpu.grade.2,decent
|
||||
item.gpu.grade.3,clearly worn
|
||||
item.gpu.grade.4,badly worn
|
||||
point.none.1,There's nothing wrong with it. You misread it.
|
||||
point.none.2,Where? Don't make things up if you're not buying.
|
||||
point.worn.1,"...Fine, it has that. I'll knock something off."
|
||||
point.worn.2,"Sharp eyes. All right, this price."
|
||||
point.fake.1,...You caught it. It's a reflashed one. I'll price it for what it is.
|
||||
point.fake.2,"Tch, not the original chip. Fine, the real chip's price."
|
||||
lbl.fan.0,Blades clean
|
||||
lbl.fan.1,Blades dusty
|
||||
lbl.fan.2,Blade chipped
|
||||
lbl.fingers.0,Bright
|
||||
lbl.fingers.1,Dull
|
||||
lbl.fingers.2,Oxidized
|
||||
lbl.print.0,Matches the model
|
||||
lbl.print.1,Another model printed
|
||||
lbl.print.2,"Reprinted, crooked"
|
||||
lbl.said," (seller said: {0})"
|
||||
lbl.point,Point out
|
||||
lbl.edit,Edit
|
||||
cust.fake.1,That's not what the label says. You trying to pass off a fake?
|
||||
cust.fake.2,The model doesn't match. That isn't the chip it claims.
|
||||
cust.worn.1,That's not what you wrote. You left out the flaws.
|
||||
cust.worn.2,The condition on the label is false. Not at this price.
|
||||
lbl.row.fan,Blades
|
||||
lbl.row.fingers,Contacts
|
||||
lbl.row.bracket,Bracket
|
||||
lbl.row.print,Back print
|
||||
lbl.row.serial,Serial
|
||||
lbl.row.seal,Seal
|
||||
lbl.bracket.0,Intact
|
||||
lbl.bracket.1,Scratched
|
||||
lbl.serial.0,Valid
|
||||
lbl.serial.1,Bad factory code or length
|
||||
lbl.serial.2,Tier code does not match
|
||||
lbl.seal.0,Intact
|
||||
lbl.seal.2,Missing
|
||||
item.guide.name,Graphics Card Appraisal Guide
|
||||
item.guide.desc,A guide for identifying counterfeit graphics cards and determining their value.
|
||||
lbl.row.spec,Model
|
||||
news.prehalving.title,PSC Halving Ahead
|
||||
news.prehalving.desc,Miners will receive half as many coins per night in three days. Holders expect the price to rise.
|
||||
tab.home,Home
|
||||
tab.bank,Bank
|
||||
tab.poinbase,Poinbase
|
||||
tab.web3,Web3
|
||||
home.enter,Enter
|
||||
home.open,Open
|
||||
home.summary,Credits {0} | On-chain assets about {1} credits
|
||||
home.lastnight,"Night of day {0}: mined {1} PSC, {2} / {3} rigs powered"
|
||||
entry.bank,Bank
|
||||
entry.bank.l1,"Deposits, withdrawals, rent"
|
||||
entry.bank.l2,Credits {0}
|
||||
entry.poinbase,Poinbase
|
||||
entry.poinbase.l1,Compliant exchange
|
||||
entry.poinbase.l2,PSC {0} credits
|
||||
entry.web3,Web3
|
||||
entry.web3.l2,About {0} credits
|
||||
entry.help,Help
|
||||
entry.help.l1,Web3 handbook
|
||||
bank.cash,Credits: {0}
|
||||
bank.rent,"Rent: {0} credits, due in {1} days"
|
||||
bank.crc,Poinbase account (CRC): {0}
|
||||
poin.account,"Poinbase account: CRC {0}, PSC {1}"
|
||||
avg.line,{0} average buy price: {1} credits
|
||||
avg.short,avg. buy {0}
|
||||
avg.none,—
|
||||
col.asset,Asset
|
||||
col.amount,Amount
|
||||
col.value,Value
|
||||
col.avg,Avg. buy
|
||||
bank.cash.k,Credits
|
||||
bank.rent.k,Rent
|
||||
bank.rent.v,"{0}, due in {1} days"
|
||||
bank.crc.k,Poinbase account (CRC)
|
||||
poin.account.h,Poinbase account
|
||||
trade.h,Trade
|
||||
web3.wallet.h,On-chain wallet
|
||||
stable.ok,Pegged
|
||||
stable.depeg,Depegged
|
||||
stable.warn,Warning: staking reserve coverage low
|
||||
stable.spiral,Collapsing
|
||||
aml.taint,Account taint share: {0}%
|
||||
mixer.h,Mixer
|
||||
mixer.ok,Status: operating normally
|
||||
mixer.sanctioned,Status: sanctioned ({0} more day(s)). Coins withdrawn meanwhile are flagged.
|
||||
mixer.pending,Pending deposits
|
||||
mixer.none,No pending deposits.
|
||||
mixer.col.taint,Taint
|
||||
mixer.col.ready,Ready
|
||||
mixer.day,Day {0}
|
||||
mixer.deposit,Deposit
|
||||
mixer.balance,Balance: {1} {0}
|
||||
mixer.rounds,Rounds
|
||||
mixer.preview,"Expect {0} {1} back, taint down about {2}%, ready on day {3}."
|
||||
mixer.go,Deposit to mixer
|
||||
mixer.min,Deposits must be worth at least {0} credits.
|
||||
mixer.done,Deposited {0} {1}; back on day {2}.
|
||||
mixer.upgrade.title,Mixer
|
||||
mixer.upgrade.desc,"Unlocks the mixer in the terminal's Gray Net page: deposit tainted coins, get them back days later with less taint. Cash-outs of freshly mixed coins are screened harder; during crackdowns the mixer may be sanctioned and coins withdrawn meanwhile are flagged."
|
||||
news.sanction.title,Mixer put on sanctions list
|
||||
news.sanction.desc,Security has sanctioned a batch of mixing services. Funds withdrawn from mixers in the next few days will be treated as suspicious.
|
||||
nightlog.mixer,Mixer returned {0} {1}; taint {2} -> {3}.
|
||||
nightlog.mixer_flag," (withdrawn during sanctions; address flagged)"
|
||||
nightlog.mixer_rug,The mixer's operator ran off with it: {0} {1} never came back.
|
||||
web3.sub.trade,Trade
|
||||
gray.sub.mixer,Mixer
|
||||
msg.frozen,Those coins are frozen until they thaw.
|
||||
wallet.frozen,"{0}: {1} frozen, thaws on day {2}"
|
||||
nightlog.crt_freeze,The black market handed over addresses during the crackdown: {0} of your CRT is frozen until day {1}.
|
||||
nightlog.thaw,Frozen {0} {1} thawed.
|
||||
news.crtfreeze.title,Black market freezes some CRT addresses for the crackdown
|
||||
news.crtfreeze.desc,Word is the black market gave security a list of CRT addresses in exchange for being left alone. Holders with low standing are likelier to be frozen.
|
||||
black.upgrade.title,Web3 Shop
|
||||
black.upgrade.desc,"Unlocks the shop in the terminal's Gray Net page: the black-market faction's on-chain arm. Weekly shelves of contraband, occasionally high-tech goods and GPUs (at a markup); buy spot, or order and wait for a courier. Coin only (PSC, CRT, CRA, Ponero), tainted coin accepted. Needs black-market standing; offline during crackdowns."
|
||||
black.offline,The shop's on-chain entrance is offline during the crackdown.
|
||||
black.closed,You need black-market standing of {0} to enter the shop (currently {1}).
|
||||
black.sub.buy,Buy
|
||||
black.shop.h,Spot counter
|
||||
black.rep,Black-market standing {0}
|
||||
black.empty,Sold out for this week.
|
||||
black.offer,{0} x{1} {2} credits
|
||||
black.buy,Buy
|
||||
black.bought,Deal done: {0} is in storage.
|
||||
black.pay.h,Payment
|
||||
black.desk.h,Ponero desk
|
||||
black.desk.left,Left today: {0} (limit {1})
|
||||
black.desk.price,Ponero price: {0}
|
||||
black.desk.swap,Swap
|
||||
black.desk.in,Into Ponero
|
||||
black.desk.out,Out of Ponero
|
||||
black.desk.go,Swap
|
||||
black.desk.fail,"Swap failed: balance, limit or amount is wrong."
|
||||
black.sub.orders,Orders
|
||||
black.rugged,The platform is down; nobody will reopen for {0} more days.
|
||||
black.seller,"{1} trades, {2}% positive"
|
||||
black.orders.h,Order catalog
|
||||
black.order,Order
|
||||
black.mode.Escrow,Escrow
|
||||
black.mode.Advance,Advance release
|
||||
black.ordered,"Ordered: {0}, due day {1}."
|
||||
black.mine.h,My orders
|
||||
black.mine.none,No orders yet.
|
||||
black.mine.line,"{0} ({1}, {2}): {3}, day {4}"
|
||||
black.state.Pending,in transit
|
||||
black.state.Ready,arrived
|
||||
black.state.Done,picked up
|
||||
black.state.Refunded.scam,"seller ran, refunded"
|
||||
black.state.Lost.scam,"seller ran, money gone"
|
||||
black.state.Lost.rug,"platform rugged, money gone"
|
||||
black.state.Lost.intercept,intercepted
|
||||
black.forum.h,Forum intel
|
||||
black.forum.quiet,Quiet lately.
|
||||
black.forum.scam,Someone says {0} takes the money and never ships.
|
||||
black.forum.rug,"Withdrawals have been slow lately, the site is running promos, and a lot of complaint threads got deleted."
|
||||
nightlog.bm.scam_refund,Black market: seller {0} ran; the escrow for {1} was refunded.
|
||||
nightlog.bm.scam_loss,Black market: seller {0} took the advance and ran; {1} is gone ({2} credits).
|
||||
nightlog.bm.intercept,Black market: the parcel with {0} was intercepted; {1} credits of payment lost.
|
||||
nightlog.bm.rug,Black market: the platform rugged; the in-transit funds for {0} ({1}) are gone.
|
||||
nightlog.bm.reopen,Black market: someone reopened at the old spot.
|
||||
news.bmrug.title,Black-market platform rugged
|
||||
news.bmrug.desc,"The black market's on-chain entrance went dark overnight, wiping out all escrow and advance funds. A new entrance will appear in a few days."
|
||||
courier.name,Courier
|
||||
courier.line1.1,Delivery's here.
|
||||
courier.line1.2,Package for you.
|
||||
courier.line2.1,Don't tell me what's inside. I don't want to know.
|
||||
courier.line2.2,Dropped it here. I'm gone.
|
||||
gray.sub.black,Shop
|
||||
black.stock,{0} left
|
||||
black.price,{0} credits
|
||||
black.noadvance,No advance release
|
||||
black.kind.gpu,GPU condition {0}%
|
||||
black.kind.Contraband.1,Contraband (low)
|
||||
black.kind.Contraband.2,Contraband (mid)
|
||||
black.kind.Contraband.3,Contraband (high)
|
||||
black.kind.Tech,High-tech (markup)
|
||||
nightlog.bm.ready,Black market: {0} arrived; a courier will come by once you open.
|
||||
guide.web3.title,Web3 Handbook
|
||||
guide.web3.text,"Bank and trading: the Bank page is read-only and shows cash, rent and the CRC in your Poinbase account. Poinbase's Funds page handles deposits and withdrawals; pick the coin first: CRC can go through the bank account or a wallet, every other coin only through a wallet. Depositing from the bank turns credits into CRC in your Poinbase account; withdrawing to the bank turns CRC back into credits and goes through compliance screening, which looks at the Poinbase account's taint. Withdrawing to a wallet needs a payee address and a few confirmations before it arrives; the gas fee is fixed at the normal tier and taken from the coin sent. A wrong address format or checksum is rejected; a correctly formatted address nobody uses means the coins are gone.¶Trading: PSC stands for Probably Stolen Coin, the coin mined by GPUs and miners. Poinbase spot has two pairs, PSC/CRC and SPARK/CRC, following the coin picked on the chart. Buys and sells are both entered as an amount of the traded coin; the preview shows the quote coin paid or received, the average price includes the fee and the slippage does not.¶The Web3 trade page can swap any two coins, always through CRC: with CRC on one side it uses one pool, otherwise two pools, with two fees and stacked slippage; the preview shows the amount received, the pools crossed and the loss. Stablecoin swaps (CRT or CRA against CRC) use stable pools: a {StableFee:%} fee and almost no slippage near the peg; during a depeg liquidity thins, and in a collapse it is pulled and slippage jumps.§Hardware wallets: on-chain coins sit in PLEDGER hardware wallets, each with its own balances and taint. A wallet is an item: drag it onto the trading terminal to load it. Open it on the terminal's Wallets page; connect and disconnect at the top right of the terminal. Trading on the Web3 page and the shop and mixer on the Gray Net page use the connected wallet; with no wallet or no connection they are view-only and every balance reads 0. Coin-paying customers pay into the connected wallet.¶Payments (shop, mixer, Ponero desk, listing fees) start as an invoice on the terminal; type the payee address on the wallet and hold ✓ to sign. The last two characters of an address are a checksum, so a one-character typo is usually caught; once in a while it happens to be valid and the coins go to an address nobody uses. DEX swaps also need a signature on the wallet.¶Poinbase is a custodial account; deposits are sent from a wallet to Poinbase's deposit address (only PSC, CRC and SPARK; the compliant exchange takes neither the black market's CRT nor the Revolution's CRA, and the wallet blocks sending them to the deposit address) and withdrawals are started on Poinbase's Funds page. The Explorer on the Wallets page looks up transfers by address and shows only transfers that really happened: every movement in and out of your wallets (transfers, DEX swaps and other contract calls, miner payouts, withdrawals, coins others send you); Ponero is a privacy coin and never shows. More hardware wallets are sold by Dr. Jackson; drag one onto the trading terminal to add it, up to {WalletMax}. The shop has cheaper ones. A wallet you no longer want can be destroyed on the Wallets page; its coins are lost for good, and anything sent to its address afterwards is lost too.¶Transfers pay a gas fee: slow, normal or fast, and gas prices rise and fall over roughly a week; when the network is congested gas fees rise and slow transactions may be dropped from the mempool. Check the full address before sending.§Staking: CRA staked in the Revolution pool earns a daily rate that compounds into the stake; withdrawing means requesting first and waiting four days, with no interest while waiting and no way to take it early. CRA is partly collateralized: each CRA is backed by the CRC reserve the Revolution holds and by the balance token SPARK; reserve coverage and the collateral ratio are shown on the staking page. Interest is paid in new uncollateralized CRA, which dilutes reserve coverage, faster the more is staked; when coverage is too low the Revolution cuts the rate. The Revolution sometimes diverts the reserve, preceded by rumors: that is the warning. If coverage then falls below {CraCrashRatio:%} it collapses: CRA is worthless within three days and four days of unlocking is too slow; above that there is only a discount, and money from raiding the upper class slowly refills the reserve.¶Official minting: deposit CRC and SPARK (ratio per the current collateral ratio; the preview shows what is needed) to mint CRA, queued {CraMintDaysMin}-{CraMintDaysMax} days; the minted CRA goes straight into staking. Burning turns CRA back into CRC and SPARK, waiting as long as the unlock period; when the reserve is short the CRC share is cut by coverage. Queued mints and burns may be dishonored in full by the Revolution: the nightly chance is how far the CRA price is below 1 times {CraRugPerDepeg}; if the price is not below 1 it cLine truncated
|
||||
courier.odd1,...Package is here.
|
||||
courier.odd2,(His hand stays in his pocket.) Sign here.
|
||||
courier.sign,Sign
|
||||
courier.refuse,Refuse
|
||||
courier.signed,"Good. Don't move, Security."
|
||||
courier.refused,"...Fine, forget it."
|
||||
black.state.Lost.seized,seized
|
||||
black.state.Lost.refused,refused
|
||||
black.forum.easy,"Too smooth lately: sellers ship faster than ever, and there are new accounts nobody has seen."
|
||||
black.forum.busted,"Word is {0} got arrested, and the order records are still around."
|
||||
nightlog.bm.trap.honeypot,"Black market: the platform was taken over by enforcement; your {0} was traced, crime logged {1}."
|
||||
nightlog.bm.trap.seller,"Black market: a seller was arrested and the order records implicate you: {0}, crime logged {1}."
|
||||
tab.mining,Mining
|
||||
courier.sign.say,I'll sign.
|
||||
courier.refuse.say,Not taking it. Send it back.
|
||||
black.forum.busted_buyer,"Word is a batch of buyers got arrested, and the sale records are still on the platform."
|
||||
nightlog.bm.sale_sold,Black market: your {0} sold for {1}; payout on day {2}.
|
||||
nightlog.bm.sale_paid,"Black market: payout of {1} for {0} arrived (CRT), taint {2}."
|
||||
nightlog.bm.sale_fake,Black market: the buyer saw that {0} is a fake and returned it; your rating dropped.
|
||||
nightlog.bm.sale_rug,Black market: the platform rugged; your {0} and the payout ({1}) are gone.
|
||||
black.sub.sell,Sell
|
||||
black.sell.h,Sell
|
||||
black.sell.mult,Price multiplier
|
||||
black.sell.none,Nothing sellable in storage.
|
||||
black.sell.rating,Rating {0}%
|
||||
black.mine.sale,{0} ref {1} price {2} (x{3}): {4}
|
||||
black.sale.Listed,listed
|
||||
black.sale.Paid,paid
|
||||
black.sale.Lost,"platform rugged, gone"
|
||||
black.sale.Delisted,taken down
|
||||
black.sale.Delisted.fake,buyer spotted the fake and returned it
|
||||
black.kind.gpunew,GPU brand new
|
||||
merchant.GpuNew,New GPUs
|
||||
merchant.GpuUsed,Used GPUs
|
||||
merchant.Arms,Arms
|
||||
merchant.Docs,Keycards & chips
|
||||
merchant.Pharma,Pharma
|
||||
merchant.Bulk,Bulk
|
||||
black.days,{0} days delivery
|
||||
black.sell.listedall,Listed {0} items.
|
||||
merchant.Rigs,Rigs & power
|
||||
merchant.Modules,Modules
|
||||
merchant.GunMods,Gunsmith parts
|
||||
merchant.Chem,Chemicals
|
||||
merchant.Brewer,Brewing
|
||||
merchant.Farm,Hydroponics
|
||||
merchant.Husbandry,Husbandry
|
||||
merchant.Miner,Mining supplies
|
||||
merchant.Water,Water
|
||||
merchant.Storage,Storage
|
||||
merchant.Tools,Tools
|
||||
merchant.Luxury,Luxury
|
||||
black.kind.Goods,Goods
|
||||
merchant.Elite,Elite shop
|
||||
merchant.Personal,Private seller
|
||||
black.pay.confirm,Invoice
|
||||
black.pay.to,Payee address: {0}
|
||||
black.pay.cancel,Void
|
||||
pay.mix,Mixer {0} {1}
|
||||
pay.swap,Ponero desk {0} {1}
|
||||
black.edit.cancel,Cancel
|
||||
merchant.Platform,Platform
|
||||
black.platform.line,Platform spot instant delivery
|
||||
black.orders.in,Bought
|
||||
black.orders.out,Selling
|
||||
black.desk.pair,PONERO [privacy coin] price {0}
|
||||
black.pay.amount,Amount: {0} {1} (about {2} credits)
|
||||
black.pay.wallet,Pay from wallet
|
||||
hw.total,Total ≈ {0} credits
|
||||
hw.pending.bill,Unpaid: {0}
|
||||
hw.pending.sign,To sign: {0}
|
||||
hw.send,Send
|
||||
hw.review,Signature request
|
||||
hw.to,Payee address
|
||||
hw.avail,Available {1} {0}
|
||||
hw.amount,Amount
|
||||
hw.bill,Invoice: {0} {1} {2}
|
||||
hw.fill,Fill invoice amount
|
||||
hw.next,✓ Next × Back
|
||||
hw.err.format,Malformed address.
|
||||
hw.err.checksum,Address checksum failed.
|
||||
hw.err.self,That is this wallet's own address.
|
||||
hw.err.asset,The invoice asks for {0}.
|
||||
hw.err.short,Less than the invoice: {0} {1}.
|
||||
hw.err.nobill,No unpaid invoice for this payee.
|
||||
hw.review.h,Review
|
||||
hw.contract,Contract call
|
||||
hw.review.to,Payee address
|
||||
hw.review.amount,{0} {1} (about {2} credits)
|
||||
hw.review.bill,Invoice: {0}
|
||||
hw.review.unknown,No transaction history at this address.
|
||||
hw.review.over,Overpaying {0} {1}; not refunded.
|
||||
hw.hold,Hold ✓ to sign × Reject
|
||||
hw.tx.h,Transaction
|
||||
hw.tx.signing,Signing…
|
||||
hw.tx.mempool,Broadcast; waiting in the mempool…
|
||||
hw.tx.packed,Included in block #{0}
|
||||
hw.tx.confirm,Block #{0} confirmation {1}/{2}
|
||||
hw.skip,Skip
|
||||
hw.done.h,Confirmed
|
||||
hw.done.block,Block #{0}
|
||||
hw.done.sent,{0} {1} → {2}
|
||||
hw.done.void,Nobody uses this address. The coins are gone.
|
||||
hw.back,Back
|
||||
hw.rejected,Signature rejected on the wallet.
|
||||
hw.wait,Confirm on the wallet.
|
||||
hw.swap,Swap {0} {1} → about {2} {3}
|
||||
tab.wallets,Wallets
|
||||
hw.wallet.n,Wallet {0}
|
||||
hw.review.own,Own wallet: {0}
|
||||
hw.review.poinbase,Poinbase deposit address
|
||||
poin.deposit,Deposit address: {0}
|
||||
wallets.count,Wallets {0}/{1}
|
||||
wallets.col.name,Name
|
||||
wallets.col.addr,Address
|
||||
wallets.col.taint,Taint
|
||||
wallets.open,Open
|
||||
wallets.use,Connect
|
||||
wallets.current,Connected
|
||||
wallets.added,Added {0}: {1}
|
||||
nightlog.drained,"The coins in {0} were moved out, about {1} credits."
|
||||
item.hwwallet.name,PLEDGER hardware wallet
|
||||
item.hwwallet.desc,Large-screen hardware wallet. Drag it onto the trading terminal to add a wallet (up to 5).
|
||||
poin.empty,The account is empty.
|
||||
hw.copy,Copy
|
||||
hw.paste,Paste
|
||||
hw.copied,Address copied.
|
||||
hw.copied.addr,Copied {0}
|
||||
hw.balance.frozen," (frozen {0})"
|
||||
wallets.destroy,Destroy
|
||||
wallets.destroy.sure,Confirm
|
||||
wallets.destroyed,Destroyed {0}: {1}
|
||||
wallets.destroy.warn,Destroying {0} permanently loses its coins. Press again to confirm.
|
||||
payout.label,Payout
|
||||
payout.unset,Not set
|
||||
payout.set,Set address
|
||||
payout.h,Payout address
|
||||
payout.cur,Current: {0}
|
||||
payout.pick,Own wallets:
|
||||
payout.manual,Or enter an address:
|
||||
payout.clear,Clear
|
||||
payout.err,Invalid address.
|
||||
nightlog.mined.lost,"{0} PSC mined was lost: no payout address set, or its wallet was destroyed."
|
||||
wallets.none,No wallet loaded. Drag a hardware wallet onto the terminal.
|
||||
web3.err.noconn,No wallet is connected.
|
||||
web3.connect,Connect wallet
|
||||
web3.disconnect,Disconnect
|
||||
web3.conn,{0} {1}
|
||||
hw.balance.value,≈ {0}
|
||||
wallets.rename,Rename
|
||||
wallets.rename.h,New name for {0}
|
||||
wallets.rename.ok,OK
|
||||
hw.fee.slow,Slow
|
||||
hw.fee.normal,Normal
|
||||
hw.fee.fast,Fast
|
||||
hw.fee,Gas fee {0} {1} (about {2} credits)
|
||||
hw.confs,{0} confirmations needed
|
||||
hw.congested,Network congested
|
||||
hw.congested.slow,Network congested: slow fee may be dropped from the mempool
|
||||
hw.recent,Recent
|
||||
hw.recent.out,→ {0} {1} {2}
|
||||
hw.recent.in,← {0} {1} {2}
|
||||
hw.review.history,Address in your history
|
||||
hw.tx.stuck,Queued in the mempool…
|
||||
hw.tx.dropped,Dropped from the mempool. Nothing was sent; the gas fee is still charged.
|
||||
hw.dropped.h,Not sent
|
||||
hw.err.fee,Not enough to cover the gas fee.
|
||||
news.congest.title,Chain congestion
|
||||
news.congest.desc,An airdrop rush has clogged the chain. Gas fees are several times higher and low-fee transactions may be dropped from the mempool.
|
||||
news.phish.title,Poinbase notice: deposit address migration
|
||||
news.phish.desc,Poinbase has upgraded its wallet system. The old deposit address will be retired; please send assets to the new address {0}.
|
||||
black.forum.phish,"Someone posted the mixer's new address: {0}, saying the old one is being watched."
|
||||
hw.gas,Gas ×{0}
|
||||
web3.sub.stake,Staking
|
||||
stake.h,Revolution staking pool
|
||||
stake.rate,Daily rate {0}%; withdrawals wait {1} days with no interest
|
||||
stake.low,Reserve coverage low; rate cut
|
||||
stake.cra,CRA price {0} {1}
|
||||
stake.none,Nothing staked.
|
||||
stake.col.wallet,Wallet
|
||||
stake.col.amount,Staked
|
||||
stake.col.queue,Unlocking
|
||||
stake.day," (day {0})"
|
||||
spark.price,Balance token SPARK {0} credits
|
||||
stake.ops,{0}
|
||||
stake.avail,CRA {0} Staked {1}
|
||||
stake.do,Stake
|
||||
stake.undo,Request withdrawal
|
||||
stake.sum.in,Stake {0} CRA
|
||||
stake.sum.out,Request withdrawal of {0} CRA (arrives in {1} days)
|
||||
stake.done.in,Staked {0} CRA.
|
||||
stake.done.out,Requested withdrawal of {0} CRA; back in the wallet on day {1}.
|
||||
nightlog.stakeint,Staking interest +{0} CRA.
|
||||
nightlog.unstaked,{0} CRA withdrawn from staking returned to {1}.
|
||||
news.crawarn.title,Unrest at the Revolution staking pool
|
||||
news.cralow.title,Revolution cuts staking rate
|
||||
stake.avail2,SPARK {0}
|
||||
poin.sub.spot,Spot
|
||||
poin.sub.perp,Perps
|
||||
perp.h,Perpetual futures
|
||||
perp.acct,Margin account CRC {0}
|
||||
perp.debt,Debt {0}; items are seized in {1} days. No new positions or cash-outs until it is cleared.
|
||||
perp.banned,Perp account banned for {0} more days.
|
||||
perp.none,No positions.
|
||||
perp.col.pos,Position
|
||||
perp.col.notional,Notional Value
|
||||
perp.col.price,Entry → price
|
||||
perp.col.pnl,PnL
|
||||
perp.col.liq,Liq. price
|
||||
perp.long,Long
|
||||
perp.short,Short
|
||||
perp.rate,{0} price {1} funding {2}%/night
|
||||
perp.fund,Insurance fund {0}
|
||||
perp.open,Open
|
||||
perp.margin,Margin amount (CRC)
|
||||
perp.do.open,Open
|
||||
perp.do.add,Add margin
|
||||
perp.do.close,Close
|
||||
perp.opened,"Opened {0} {1}: margin {2} CRC, {3}×."
|
||||
perp.added,Added {0} CRC of margin.
|
||||
perp.closed,Closed; {0} CRC back in the account (PnL {1}).
|
||||
perp.deficit,"Equity fell short by {0}, covered by the insurance fund and debt."
|
||||
perp.err.Banned,The perp account is banned.
|
||||
perp.err.Debt,You have debt; no new positions.
|
||||
perp.err.Leverage,Leverage is above this product's limit.
|
||||
perp.err.Size,Above this product's position cap.
|
||||
perp.err.Funds,Not enough CRC in the account (the fee counts).
|
||||
perp.err.Opposite,You cannot be long and short the same product; close first.
|
||||
perp.err.NoPosition,No position.
|
||||
perp.err.Margin,Enter a margin amount.
|
||||
perp.debt.block,You owe the perps desk; no cash-outs.
|
||||
nightlog.perp.liq,{0} was liquidated; the {1} margin is gone.
|
||||
nightlog.perp.adl,The insurance fund ran dry; {0} was auto-deleveraged and gave up {1} of profit.
|
||||
nightlog.perp.interest,Perp debt accrued interest; you now owe {0}.
|
||||
nightlog.perp.seize,Overdue perp debt: seized items covered {0}.
|
||||
nightlog.perp.writeoff," {0} written off; the perp account is banned for {1} days."
|
||||
perp.slip.title,Perp debt seizure slip
|
||||
perp.preview2,Fee {0} liq. {1}
|
||||
nightlog.perp.repaid,Perp deficit: {0} CRC was taken from the Poinbase account to repay it.
|
||||
perp.err.Thin,Slippage on this order is so large it would be liquidated at once. Reduce the size or leverage.
|
||||
perp.err.Single,Only one position at a time; add margin instead.
|
||||
mat.hypertech_electronic,Hypertech electronic component
|
||||
item.asic.name,RatDigg {0} miner
|
||||
item.asic.dead.name,Burnt-out RatDigg {0} miner
|
||||
item.asic.desc,"Rated {0} GH/s. Rated draw {1} kJ/day. Condition {2}. A standalone miner: needs a battery to run, takes modules."
|
||||
item.asic.dead.desc,Burnt out. Drag electronic components onto it to repair: now {0} × {1}. Health drops by 20 once fixed.
|
||||
item.asic.dead.fixed,Already fixed.
|
||||
merchant.Asic,Miner dealer
|
||||
black.kind.asic,Miner condition {0}%
|
||||
black.kind.asicnew,Miner new
|
||||
news.erawarn.title,RatDigg is about to launch a new generation of miners
|
||||
news.erawarn.desc,"The dedicated-miner maker has announced new hardware, and the industry expects big farms to swap out en masse before long. Some say the good days of GPU mining are numbered."
|
||||
news.era.title,The miner era
|
||||
news.era.desc,A new generation of dedicated miners is in mass production and the big farms have halved their power costs. Network hash will climb and GPU miners' returns will be diluted.
|
||||
web3.sub.predict,Predict
|
||||
predict.h,Prediction markets
|
||||
predict.acct,{0}: CRC {1}
|
||||
predict.none,No open markets today.
|
||||
predict.closed,closed
|
||||
predict.row,Yes {0} No {1}
|
||||
predict.held,"holding {0} x{1}, cost {2}"
|
||||
predict.yes,Yes
|
||||
predict.no,No
|
||||
predict.void,void
|
||||
predict.result,Day {0} {1} result: {2} {3}
|
||||
predict.pick,Trade
|
||||
predict.price,Price per share: Yes {0} No {1}
|
||||
predict.pos,{0}: {1} x{2}
|
||||
predict.pos2,Cost {0} pays {1}
|
||||
predict.sum.buy,Buy {1} for {2} CRC: {0}
|
||||
predict.sum.sell,Sell prediction position: {0}
|
||||
predict.closed.note,"Closed, waiting for settlement."
|
||||
predict.preview,"Buy {0}: about {1} shares (avg {2}), net {3} if right"
|
||||
predict.buy.yes,Buy Yes
|
||||
predict.buy.no,Buy No
|
||||
predict.sell,Sell all
|
||||
predict.bought,"Bought {0} for {2}, pays {1} if right."
|
||||
predict.sold,"Sold, received {0}."
|
||||
predict.err.Closed,This market is closed.
|
||||
predict.err.Amount,Invalid amount.
|
||||
predict.err.Funds,Not enough CRC in the wallet.
|
||||
predict.err.Cap,Over this market's position limit.
|
||||
predict.err.Opposite,You hold the other side; sell it first.
|
||||
predict.err.NoPosition,No position in this market.
|
||||
predict.win.one,Day {0}
|
||||
predict.win.range,Days {0}-{1}
|
||||
predict.q.event,"{0}: ""{1}"" happens"
|
||||
predict.q.faction,{0}: {1} starts an operation
|
||||
predict.q.purity,{0}: {1} purity >= {2}
|
||||
predict.q.price,{0}: {1} price >= {2}
|
||||
predict.faction.FACTION_SECURITY,Security
|
||||
predict.faction.FACTION_REVOLUTION,Revolution
|
||||
predict.faction.FACTION_LOWER_LEVEL,Lower level
|
||||
predict.faction.FACTION_UPPER_LEVEL,Upper level
|
||||
predict.faction.FACTION_BLACK_MARKET,Black market
|
||||
predict.purity.gutter,Lower water
|
||||
predict.purity.rust,Upper water
|
||||
nightlog.predict.win,"Prediction right: ""{0}"", paid out {1}."
|
||||
nightlog.predict.lose,"Prediction wrong: ""{0}"", stake {1} lost."
|
||||
nightlog.predict.void,"Prediction void: ""{0}"", stake {1} refunded."
|
||||
nightlog.predict.caught,"Insider bet caught: ""{0}"", stake and winnings {1} confiscated, fraud on record."
|
||||
predict.tab.markets,Markets
|
||||
predict.tab.intel,Intel
|
||||
predict.acct.crt,{0}: CRT {1}
|
||||
predict.tier.0,low
|
||||
predict.tier.1,mid
|
||||
predict.tier.2,high
|
||||
predict.clue.tip,Tip ({0}): says {1}
|
||||
predict.clue.queued,Scheduled: starts day {0}
|
||||
predict.clue.queued2,"Scheduled: day {0} ""{1}"""
|
||||
predict.clue.cool,Event active or on cooldown
|
||||
predict.clue.busy,Faction op running; no new one soon
|
||||
predict.clue.halving,Halving day {0}; anchor ramps the week before
|
||||
predict.clue.anchor,Price anchor now {0}
|
||||
predict.clue.gas,Recent gas: {0}
|
||||
predict.clue.drain,Drain per night {0}
|
||||
predict.clue.era,"Random in days {0}-{1}, announced ahead"
|
||||
predict.clue.era.warned,Announced: starts days {0}-{1}
|
||||
predict.q.gas,{0}: gas index >= {1}
|
||||
predict.q.cra,{0}: CRA warning issued
|
||||
predict.q.era,{0}: ASIC era starts
|
||||
predict.era,ASIC era
|
||||
predict.pos3,Avg {0} now {1}
|
||||
predict.pos4,Selling now returns {0}
|
||||
intel.h,Intel broker
|
||||
intel.locked,Needs the Web3 shop and black-market standing {0}.
|
||||
intel.brief.buy,Buy situation brief ({0} CRT)
|
||||
intel.brief.none,No brief bought yet.
|
||||
intel.brief.day,Brief from day {0}
|
||||
intel.tips.h,Insider tips
|
||||
intel.tips.none,Nothing to ask about (only faction ops and the ASIC era).
|
||||
intel.tip.buy,About {0}% accurate {1} CRT
|
||||
intel.err.funds,"Not enough CRT in the wallet, or the market can no longer be bought."
|
||||
intel.brief.sum,"Situation brief, {0} CRT"
|
||||
intel.tip.sum,Insider tip {0} CRT: {1}
|
||||
intel.brief.done,Got the brief.
|
||||
intel.tip.done,They say: {0}.
|
||||
predict.brief.levels,Security {0} Rev {1} Black mkt {2} Unrest {3} Upper {4}
|
||||
predict.brief.busy,{0}: operation running
|
||||
predict.brief.queued,{0}: operation scheduled
|
||||
predict.brief.none,{0}: nothing to launch
|
||||
predict.brief.can,{0}: can launch {1}
|
||||
predict.clue.push,You moved the price {0}%: risky
|
||||
nightlog.predict.manip,"Prediction ruled manipulation: ""{0}"", stake {1} confiscated, fraud on record."
|
||||
news.manip.title,Exchange probes unusual trading
|
||||
news.manip.desc,Regulators report that someone moved the price with large spot orders and profited from derivatives and predictions; the funds were seized.
|
||||
perp.manip,Profit {0} on close ruled price manipulation and seized; perp account frozen for {1} days.
|
||||
web3.sub.ponzi,Yield
|
||||
ponzi.h,High-yield scheme
|
||||
ponzi.acct,Issuer wallet {0}: CRC {1}
|
||||
ponzi.rate,Daily rate {0}%
|
||||
ponzi.pool,Pool {0} / cap {1}
|
||||
ponzi.inflow,New deposits last night {0}
|
||||
ponzi.interest,Interest due tonight {0}
|
||||
ponzi.own,Interest paid from your pocket {0}
|
||||
ponzi.wind,Report risk: {0}
|
||||
ponzi.wind.low,low
|
||||
ponzi.wind.mid,medium
|
||||
ponzi.wind.high,high
|
||||
ponzi.idle,No scheme issued.
|
||||
ponzi.done,The scheme is closed; only one per save.
|
||||
ponzi.ops,Actions
|
||||
ponzi.rug,Rug the pool ({0})
|
||||
ponzi.rug.confirm,Click again to confirm rugging {0}
|
||||
ponzi.rugged,"Took {0}, fully tainted."
|
||||
ponzi.open,Open a scheme
|
||||
ponzi.ad,Marketing cost {0} CRC from the current wallet; signature required.
|
||||
ponzi.start,Launch
|
||||
ponzi.started,Launched.
|
||||
ponzi.err,Not enough CRC in the wallet for the marketing cost.
|
||||
nightlog.ponzi.collapse,"The scheme could not pay interest; run on the pool, {0} confiscated, fraud on record, lower-level standing wiped."
|
||||
nightlog.ponzi.reported,"The scheme was reported; pool {0} confiscated, fraud on record, lower-level standing wiped."
|
||||
news.ponzi.title,High-yield scheme collapses
|
||||
news.ponzi.desc,A high-yield scheme run in the lower levels was reported; investors mobbed it and regulators froze the funds.
|
||||
news.ponzi.rug.title,Investment scam
|
||||
news.ponzi.rug.desc,The operator of a high-yield scheme has run off with all the funds; lower-level investors lost everything.
|
||||
ponzi.start.sum,"Open high-yield scheme, daily rate {0}%, marketing {1} CRC"
|
||||
ponzi.rug.sum,Rug the pool {0}
|
||||
ponzi.err.wallet,Sign with the issuer wallet.
|
||||
predict.clue.counter,"Intel: scheduled (counter informant, rumor slip)"
|
||||
web3.sub.airdrop,Airdrops
|
||||
air.h,Airdrops
|
||||
air.none,No airdrops to claim right now.
|
||||
air.row,{0} reward {1} CRC {2} until day {3}
|
||||
air.claim,Claim
|
||||
air.unlimited,approve {0} unlimited
|
||||
air.limited,approve {0} {1}
|
||||
air.approvals,Approvals of {0}
|
||||
air.approvals.none,No approvals.
|
||||
air.approval,{0}: {1}
|
||||
air.revoke,Revoke
|
||||
air.sum,Claim airdrop {0} ({1})
|
||||
air.claimed,Received {0} CRC.
|
||||
air.auth,Authorize wallet
|
||||
air.unauth,Not authorized
|
||||
air.authed,Authorized: {0}
|
||||
air.authed.msg,Wallet authorized for {0}.
|
||||
air.auth.sum,Authorize {0} to act for this wallet. Scope: {1}.
|
||||
air.err.unauth,Authorize the wallet for this airdrop first.
|
||||
air.revoke.sum,Revoke {0}'s {1} approval
|
||||
air.revoked,Approval revoked.
|
||||
air.err.wallet,Sign with the approving wallet.
|
||||
pool.h,Third-party yield pools (CRC)
|
||||
pool.none,None right now.
|
||||
pool.col.name,Pool
|
||||
pool.col.rate,Daily
|
||||
pool.col.reserve,Reserve
|
||||
pool.col.lock,Timelock
|
||||
pool.col.audit,Audit
|
||||
pool.col.mine,Mine
|
||||
pool.yes,yes
|
||||
pool.no,no
|
||||
pool.pending,withdrawing
|
||||
pool.closed,(closed)
|
||||
pool.deposit,Deposit
|
||||
pool.withdraw,Withdraw
|
||||
pool.withdraw.lock,Request withdrawal ({0} days)
|
||||
pool.err.cap,Over the pool cap; {0} left.
|
||||
pool.err.none,No deposit.
|
||||
pool.sum.in,Deposit to {0}: {1} CRC
|
||||
pool.sum.out,Withdraw {1} CRC from {0}
|
||||
pool.done.in,Deposited {0} CRC to {1}.
|
||||
pool.done.out,Withdrew {0} CRC.
|
||||
pool.done.lock,"Requested {0} CRC, arrives on day {1}."
|
||||
nightlog.scam.drain,"{1} {2} in {0} was taken by ""{3}"" through an approval."
|
||||
nightlog.scam.rug,"Yield pool ""{0}"" rugged; {1} CRC from {2} is gone."
|
||||
nightlog.scam.dry,"Yield pool ""{0}"" ran out of reserve and closed; {1} CRC returned to {2}."
|
||||
nightlog.scam.paid,"Withdrawal from ""{0}"" arrived: {2} received {1} CRC."
|
||||
nightlog.scam.fakepay,Forged transfer: {0}
|
||||
nightlog.scam.sent,"The {0} {1} sent to the ""support"" safe address went to a scammer."
|
||||
coinpay.intro,I'll pay in {0}; it takes a moment to confirm on chain.
|
||||
coinpay.intro.fake,"Already sent the {0}, here's the screenshot. Hand it over, I'm in a hurry."
|
||||
coinpay.fake.entry,{0} took {1} claiming to have paid {2} credits in coin; no such transaction on chain.
|
||||
scam.support.name,Poinbase Support
|
||||
scam.support.1,"Hello, Poinbase support here. We detected an unusual login on your account and it has been flagged."
|
||||
scam.support.2,Please send {0} CRC to the safe address {1} today for verification; it will be returned right after.
|
||||
scam.support.3,"Otherwise the account will be frozen for good. I have to go, remember to send it."
|
||||
predict.sold.caught,"Insider trading caught on sale: stake and profit confiscated, fraud on record."
|
||||
predict.row.move," (last night {0} {1})"
|
||||
predict.stats.h,History (avg opening price / actual rate)
|
||||
predict.stats.row,"{0}: {1} markets, avg open {2}, happened {3}%"
|
||||
predict.kind.Event,News events
|
||||
predict.kind.Faction,Faction ops
|
||||
predict.kind.Purity,Water purity
|
||||
predict.kind.Price,PSC price
|
||||
predict.kind.Gas,Gas
|
||||
predict.kind.Cra,CRA warning
|
||||
predict.kind.Era,ASIC era
|
||||
nightlog.predict.move,"Prediction ""{0}"" moved {1} -> {2}"
|
||||
nightlog.predict.why," ({0})"
|
||||
chart.empty,{0} daily chart: no history yet; recording from today.
|
||||
chart.caption,{0} daily H {2} L {3} C {4} ({5}%)
|
||||
chart.legend,"<size=80%>green up, red down; yellow 7-day MA; bars: grey market / cyan you</size>"
|
||||
chart.legend.thr,"<size=80%>green up, red down; yellow 7-day MA; blue dashes threshold</size>"
|
||||
news.story.serpico_rev.title,Revolution holds dirt on Security
|
||||
news.story.serpico_rev.desc,"The Revolution reportedly obtained evidence of corruption inside Security. Word from the staking pool: a large sum has been injected into the Revolution's reserve, and SPARK has been firming up."
|
||||
news.story.serpico_bm.title,Black market strikes a quiet deal
|
||||
news.story.serpico_bm.desc,"An internal Security document changed hands on the black market. Darknet settlement has been noticeably steadier since, and CRT redemptions have not slipped once."
|
||||
news.story.serpico_sec.title,Security launches internal purge
|
||||
news.story.serpico_sec.desc,Security announced a full investigation into internal corruption and tighter monitoring of money flows. Poinbase is tightening cash-out screening and mixing services have been named.
|
||||
news.story.eleanor_leak.title,Nutrifruit breeding data leaked
|
||||
news.story.eleanor_leak.desc,"The lower-level paper published research that lets nutrifruit set seed again; Pastelle shares plunged. The bank custodying upper-level funds reports bad debts, and the Revolution is gaining ground."
|
||||
news.story.eleanor_return.title,Pastelle recovers stolen data
|
||||
news.story.eleanor_return.desc,"Pastelle confirmed it recovered stolen research data. Upper-level capital breathed a sigh of relief, and the CRC custodian bank was upgraded."
|
||||
news.story.lun_arrested.title,Officer Lun arrested for abuse of power
|
||||
news.story.lun_arrested.desc,Security arrested Officer Lun on the spot for abuse of power and promised a strict crackdown on illegal trading for the next two weeks.
|
||||
tumbler.name,Tumbler
|
||||
tumbler.v1.1,Hi. I hear the terminal here is hooked up to my mixer.
|
||||
tumbler.v1.2,I wrote that thing. People call me Tumbler.
|
||||
tumbler.v1.3,It doesn't touch your goods or keep your books. It just stirs the coins.
|
||||
tumbler.v1.4,Was passing by. Wanted to see what my users look like.
|
||||
tumbler.v2.1,Things are getting rough. Security is going after on-chain mixing services.
|
||||
tumbler.v2.2,They flagged a few big addresses and traced them back to my node.
|
||||
tumbler.v2.3,"If the mixer goes down for a few days, don't panic. Coins inside won't be lost."
|
||||
tumbler.v3.1,They shut my node down. Sooner or later they'll find where I live.
|
||||
tumbler.v3.2,I've got a key drive with the mixer's signing keys on it.
|
||||
tumbler.v3.3,"If Security gets it, they can rebuild every user's history. Yours too."
|
||||
tumbler.v3.ask,Can you hide it for a few days?
|
||||
tumbler.v3.choice.hide,[Take the drive and hide it]
|
||||
tumbler.v3.choice.report,"[Agree, then tip off Security]"
|
||||
tumbler.v3.choice.sell,[Take the drive and sell it to the black market]
|
||||
tumbler.v3.thanks1,Thanks. I'll come back for it in a few days.
|
||||
tumbler.v3.thanks2,"Don't leave it lying around. If a search turns it up, we're both done."
|
||||
tumbler.v3.report1,...Okay. I'll come by later.
|
||||
tumbler.v4.back.1,I'm here for the drive.
|
||||
tumbler.v4.back.2,The node's moved somewhere new. Security won't find it anytime soon.
|
||||
tumbler.v4.back.3,Here's something for your trouble. From now on your mixer fees are half price.
|
||||
tumbler.v4.lost.1,Where's the drive?
|
||||
tumbler.v4.lost.2,...You lost it?
|
||||
tumbler.v4.lost.3,Forget it. I'll figure something out.
|
||||
tumbler.v4.sold.1,"You sold the drive to the black market, didn't you."
|
||||
tumbler.v4.sold.2,"They run the mixer now. Fees doubled, and users' money could vanish any day."
|
||||
tumbler.v4.sold.3,I won't forget this.
|
||||
tumbler.v4.none.1,Never mind. I was never here.
|
||||
item.keydrive.name,Key drive
|
||||
item.keydrive.desc,"A data stick Tumbler left with you, holding the mixer's signing keys. Contraband: if a search turns it up, it goes on your record."
|
||||
mixer.closed,The mixer has been shut down and takes no new deposits. Coins already inside come back as usual.
|
||||
news.tumbler.sanction.title,Security seizes mixing node
|
||||
news.tumbler.sanction.desc,"Security announced the seizure of a node of an on-chain mixing service, saying it facilitated money laundering. The service is temporarily down."
|
||||
news.tumbler.caught.title,Mixer operator arrested
|
||||
news.tumbler.caught.desc,The mixer operator known as Tumbler was arrested in the lower levels. Security says the mixing service has been shut down for good.
|
||||
news.tumbler.sold.title,Mixing service changes hands
|
||||
news.tumbler.sold.desc,"Word is the signing keys of a lower-level mixing service have fallen into black-market hands, and fees went up at once. Users fear for their funds."
|
||||
nightlog.tumbler.gift,Tumbler took back the key drive and left {0} CRT as thanks (sent to {1}); mixer fees halved.
|
||||
mixer.status.closed,Status: shut down
|
||||
yield.sub.pools,Yield pools
|
||||
yield.sub.mine,Issue scheme
|
||||
pool.side.h,Deposit
|
||||
ponzi.early,High-yield schemes can be issued from day {0}.
|
||||
bpay.h,Payment
|
||||
bpay.qty,Quantity
|
||||
bpay.total,Total {0} credits
|
||||
bpay.need,Pay {0} {1} wallet balance {2}
|
||||
bpay.invoice,Create invoice
|
||||
bpay.swap.h,Auto-convert to {0}
|
||||
bpay.swap.none,No other coin in the wallet is enough
|
||||
bpay.swap.need,"Pay {0} {1}, includes {2}% slippage"
|
||||
bpay.swap.btn,Convert and pay
|
||||
bpay.swap.sum,"{0}: auto-convert, pay {2} {1}, swapped to {3} before ordering"
|
||||
bpay.back,Back
|
||||
cart.fab,Cart {0}
|
||||
cart.h,Cart
|
||||
cart.empty,The cart is empty.
|
||||
cart.added,Added to cart: {0}
|
||||
cart.back,Back to shop
|
||||
cart.done,Paid for {0} items.
|
||||
cart.partial,Paid for {0} items; {1} failed (stock or balance).
|
||||
black.info.accepts,Takes: {0}
|
||||
black.info.advance.yes,advance release accepted
|
||||
black.info.advance.no,no advance release
|
||||
settings.section.ui,Interface
|
||||
settings.section.story,Story
|
||||
settings.section.difficulty,Difficulty
|
||||
settings.terminal_size,Trading terminal size
|
||||
settings.terminal_size_desc,Window size in interface units (width × height). Applies the next time the terminal opens.
|
||||
settings.tumbler_story,Tumbler storyline
|
||||
settings.tumbler_story_desc,Tumbler's visits and the keydisk errand. Turning this off stops new visits; progress already made is kept.
|
||||
settings.risk_scale,Risk multiplier
|
||||
settings.risk_scale_desc,"Multiplies the chance of scams, rug pulls, wallet poisoning, address hijacking and phishing. Applies to all saves."
|
||||
settings.mining_scale,Mining reward multiplier
|
||||
settings.mining_scale_desc,Multiplies the block reward paid to mining rigs. Applies to all saves.
|
||||
gg.header,Station Trade Commission
|
||||
gg.p1.cap,Graphics card
|
||||
gg.p1.makers,"There are two common manufacturers on the Station:\n\n - Probidia (""PB"")\n - PMD (""MD"")"
|
||||
gg.p1.note,"Whoever made it, a card's value depends only on the list price of the real chip and its health: at full health it equals the list price, at zero health only {CardValueFloor:%} is left."
|
||||
gg.fan.h,Fan Blades
|
||||
gg.fan.0,Clean (price unchanged)
|
||||
gg.fan.1,Dusty (-{CardFanDust:%})
|
||||
gg.fan.2,Chipped (-{CardFanChipped:%})
|
||||
gg.fin.h,Contacts
|
||||
gg.fin.0,Bright (price unchanged)
|
||||
gg.fin.1,Dull (-{CardFingersDark:%})
|
||||
gg.fin.2,Oxidized (-{CardFingersOxidized:%})
|
||||
gg.brk.h,Bracket
|
||||
gg.brk.0,Intact (price unchanged)
|
||||
gg.brk.1,Scratched (-{CardBracketScratch:%})
|
||||
gg.seal.h,Seal
|
||||
gg.seal.0,Intact (price unchanged)
|
||||
gg.seal.2,Missing (-{CardSealMissing:%})
|
||||
gg.wear.note,"Fan blades, contacts and bracket wear down each night and never recover; the seal is fixed. Condition also affects hashrate, wear and burnout chance."
|
||||
gg.serial.h,Serial Number
|
||||
gg.serial.cap,Back of the card (serial sticker)
|
||||
gg.serial.pb,"Probidia (""PB"")\n Valid factory codes: 11, 12, 21, 34, 47"
|
||||
gg.serial.md,"PMD (""MD"")\n Valid factory codes: 13, 22, 35, 41, 58"
|
||||
gg.print.h,Back Print
|
||||
gg.print.0,Matches the model
|
||||
gg.print.1,Shows another model (counterfeit)
|
||||
gg.print.2,"Reprinted, crooked (counterfeit)"
|
||||
gg.point.h,Pointing Out
|
||||
gg.ex.card,"Example: {0}, health {1}%"
|
||||
gg.ex.base,Base value: +{0}
|
||||
gg.ex.fan,Chipped fan: -{0}
|
||||
gg.ex.fin,Dull contacts: -{0}
|
||||
gg.ex.seal,Missing seal: -{0}
|
||||
gg.ex.total,Final value: {0}
|
||||
gg.ex.note,Every discount is a share of the base value; they are added up and deducted.
|
||||
gg.ex.fan1,Dusty fan: -{0}
|
||||
gg.ex.fin2,Oxidized contacts: -{0}
|
||||
gg.ex.brk,Scratched bracket: -{0}
|
||||
gg.ex.nodisc,No discounts: -0
|
||||
gg.ex.fake,"Stated {0}, real chip {1}: valued as the real chip"
|
||||
gg.ex.claimed,Price as the stated model: {0}
|
||||
gg.ex.gap,Difference from the quote: {0}
|
||||
gg.ex.h2,Appraisal Example: Counterfeit
|
||||
gg.ex.h3,Appraisal Example: Badly Worn
|
||||
gg.ex.h4,Appraisal Example: Lightly Used
|
||||
gg.ex.h5,Appraisal Example: Brand New
|
||||
lbl.price,Label price: {0}
|
||||
lbl.row.count,Fans
|
||||
lbl.row.pin,Power
|
||||
lbl.count.1,1 fan
|
||||
lbl.count.2,2 fans
|
||||
lbl.count.3,3 fans
|
||||
lbl.pin.0,6-pin
|
||||
lbl.pin.1,8-pin
|
||||
lbl.pin.2,Dual 8-pin
|
||||
gg.p1.body,"Graphics cards are the core of every mining rig, and the goods most often counterfeited on the used market.\nFour things show whether a card is genuine: fan count, power connector, back print and serial number. Only a card that matches its stated model on all four is genuine; any single mismatch means a counterfeit.\nA card's value depends on the model of the chip inside and its health, and every sign of wear lowers the price.\n\nThis guide provides all the knowledge needed to appraise a graphics card."
|
||||
gg.p2.h,Card Models
|
||||
gg.p2.body,"The model sets the fan count and the power connector. A counterfeit is a low-model chip in a high-model shell, and its performance and value follow the chip inside."
|
||||
gg.tier.0,"RTX 60 / RX 70: 6-pin, one fan"
|
||||
gg.tier.1,"RTX 70 / RX 80: 8-pin, two fans"
|
||||
gg.tier.2,"RTX 80 / RX 800: 8-pin, three fans"
|
||||
gg.tier.3,"RTX 90 / RX 900: dual 8-pin, three fans"
|
||||
gg.count.h,Fan Count
|
||||
gg.count.body,"The model sets the fan count: one fan on the RTX 60 and RX 70, two on the RTX 70 and RX 80, three on the RTX 80, RTX 90, RX 800 and RX 900.\nA fan count that does not match the stated model marks a counterfeit."
|
||||
gg.pin.h,Power Connector
|
||||
gg.pin.body,"The model also sets the power connector: 6-pin on the RTX 60 and RX 70, 8-pin on the RTX 70, RTX 80, RX 80 and RX 800, dual 8-pin on the RTX 90 and RX 900.\nA power connector that does not match the stated model marks a counterfeit."
|
||||
gg.serial.body,"The serial number is on a sticker on the back, as prefix, model code, hyphen, two-digit factory code, hyphen and four-digit sequence, for example PB2-21-6251."
|
||||
gg.serial.rule,"Model codes 1 to 4 stand for RTX 60 / RX 70, RTX 70 / RX 80, RTX 80 / RX 800 and RTX 90 / RX 900.\nA model code that does not match the model (the sticker belongs to the original chip), or an invalid factory code or length (a sticker added later), marks a counterfeit. The factory code only proves authenticity and does not change the price."
|
||||
gg.print.note,"A card is genuine only if fan count, power connector, print and serial number all match. A counterfeit fails at least one, but may get the others right, so check every one."
|
||||
gg.point.body,"Inspect with the magnifier. In the label bar, only the model row has a Point out model button; the four rows below it (fan count, power connector, back print, serial number) are read-only, and each of the four condition rows has its own Point out button.\nPoint out a hidden condition problem and that row switches to the true state and the price drops by the difference; point out something true and the other side refuses and your reputation suffers.\nIf any of the four proof rows does not match the stated model, point out the model: the card is then ruled a counterfeit, the model reverts to the real chip, and the price is recalculated for that chip.\n\nCards brought by appraisal guild clients work the same way: pointing out problems changes the estimate until you report the correct value."
|
||||
gg.ex.serial,Serial number: {0}
|
||||
gg.ex.h,"Appraisal Example: Chipped Fan, Dull Contacts, Missing Seal"
|
||||
rig.label.status,Status
|
||||
rig.st.cards,Cards
|
||||
rig.st.power,Power
|
||||
rig.st.hash,Hashrate
|
||||
rig.st.kj,{0} kJ/day
|
||||
lbl.point.model,Point out model
|
||||
col.crcprice,CRC price
|
||||
swap.pay,Pay
|
||||
swap.get,Receive
|
||||
swap.preview,"Receive about {0} {1} {2} pool(s), loss {3}%"
|
||||
swap.go,Swap
|
||||
swap.same,Pay and receive must be different coins.
|
||||
mint.need,Needs {0} CRC and {1} SPARK
|
||||
mint.reserve,Reserve coverage {0}% Collateral ratio {1}%
|
||||
mint.queue,Pending orders
|
||||
mint.order,"{0} {1} CRA, day {2}"
|
||||
stake.coin,Deposit coin
|
||||
stake.sum.via,"Swap {0} {1} → about {2} CRA, then stake"
|
||||
nightlog.cra.lost,The issuer did not respond: the {1} order of {0} CRA is lost.
|
||||
news.crawarn.desc,"Someone is counting the Revolution's reserve, and staked CRA may not be redeemable in full. Unlocking takes four days; some say it is time to move."
|
||||
news.cralow.desc,"The reserve ratio is running low, and the Revolution has cut the CRA staking rate to a fraction."
|
||||
poin.sub.funds,Funds
|
||||
funds.receive,Receive
|
||||
funds.send,Send
|
||||
funds.bank,Bank account
|
||||
funds.wallet,Wallet
|
||||
funds.to,To address
|
||||
funds.go,Send
|
||||
funds.sending,Sending {0} {1} to {2}
|
||||
funds.confirm,Confirmation {0}/{1}
|
||||
funds.done,{0} {1} arrived in {2}.
|
||||
funds.done.void,{0} {1} sent; the address has no owner and the coins are gone.
|
||||
funds.err.addr,Invalid address.
|
||||
funds.err.self,That is the Poinbase deposit address.
|
||||
funds.err.known,That address only accepts payments against a bill.
|
||||
funds.err.fee,The amount does not cover the gas fee.
|
||||
wallets.sub.explorer,Explorer
|
||||
explorer.search,Address
|
||||
explorer.all,Latest
|
||||
explorer.none,No transfers.
|
||||
explorer.col.block,Block
|
||||
explorer.col.amount,Amount
|
||||
explorer.mixer,Mixer
|
||||
cra.mint,Mint
|
||||
cra.burn,Burn
|
||||
mint.h,Official mint (CRC + SPARK)
|
||||
mint.sum.in,Mint {0} CRA with {1} CRC and {2} SPARK ({3}–{4} days)
|
||||
mint.sum.out,Burn {0} CRA for CRC and SPARK ({1} days)
|
||||
mint.done.in,Mint order placed; due on day {0}.
|
||||
mint.done.out,Burn order placed; due on day {0}.
|
||||
nightlog.cra.minted,"Minted {0} CRA, now staked ({1})."
|
||||
nightlog.cra.burned,"Burned {0} CRA: +{1} CRC, +{2} SPARK ({3})."
|
||||
predict.clue.subsidy,Reserve {0}%; empty forces a warning
|
||||
air.noapprove,no token allowance
|
||||
tab.gray,Gray Net
|
||||
wallets.sub.list,Wallet list
|
||||
entry.web3.l1,Decentralized trading and yield
|
||||
entry.mining.l1,Rig status and nightly payouts
|
||||
entry.gray.l1,Mixer and shop
|
||||
entry.wallets.l1,Hardware wallets and Explorer
|
||||
entry.wallets.l2,Wallets {0} / {1}
|
||||
black.sell.add,Add listings
|
||||
black.sell.back,Back to showcase
|
||||
black.sell.kinds,Listed {0}/{1} kinds
|
||||
black.sell.have,{0} listed
|
||||
black.sell.coins,Accepted coins
|
||||
black.sell.off,Take down
|
||||
black.sell.off.n,Take down ×{0}
|
||||
black.sell.nocoin,Accept at least one coin.
|
||||
black.sell.empty,Nothing listed.
|
||||
black.sell.delisted,Took down {0}; the goods are back in storage.
|
||||
black.sell.partial,Listed {0}; {1} could not be listed.
|
||||
black.sell.limit.stack,Up to {0} of each item can be listed.
|
||||
black.sell.limit.kinds,Up to {0} kinds can be listed at once.
|
||||
shelf.fab,Shelf {0}
|
||||
delist.fab,Confirm take-down {0}
|
||||
black.fee.h,Ready to list
|
||||
black.fee.line,{0} ×{1} · price {2} ({3})
|
||||
black.fee.total,Listing fee {0}
|
||||
black.fee.sum,Listing fee ({0} items)
|
||||
black.sale.Sold,"Sold; payout on day {0} in {1}"
|
||||
explorer.col.day,Day
|
||||
explorer.day,Day {0}
|
||||
explorer.pool,RatDigg pool
|
||||
explorer.desk,Ponero desk
|
||||
black.fee.pay,Pay listing fee
|
||||
explorer.col.from,From
|
||||
explorer.col.to,To
|
||||
rig.st.cond,Condition
|
||||
asic.st.dead,Burnt out
|
||||
perp.preview,Notional {0} est. avg price {1} (slippage {2}%)
|
||||
perp.sim.close,Close notional {0} est. avg price {1} (slippage {2}%)
|
||||
perp.sim.close2,Fee {0} about {1} CRC back (P/L {2})
|
||||
trade.sim.sell,Sell gets about {0} {1} avg {2} slippage {3}%
|
||||
trade.sim.buy,Buy costs about {0} {1} avg {2} slippage {3}%
|
||||
trade.amount.unit,Amount ({0})
|
||||
trade.fee,Fee {0}%
|
||||
trade.sim.thin,Exceeds pool liquidity
|
||||
news.wipe.down.title,"{0} falls {1}% in a day, {2} traders liquidated"
|
||||
news.wipe.down.desc,"Over the past day {1} long positions on {0} perps were liquidated, {2} credits in total. The Poinbase insurance fund stands at {3} credits."
|
||||
news.wipe.up.title,"{0} jumps {1}% in a day, {2} traders liquidated"
|
||||
news.wipe.up.desc,"Over the past day {1} short positions on {0} perps were liquidated, {2} credits in total. The Poinbase insurance fund stands at {3} credits."
|
||||
hot.name,Seller
|
||||
hot.intro.CRT,"Things are tense lately and this CRT is too hot to hold. I need cash, fast."
|
||||
hot.intro.PSC,"A mining farm's wallet changed hands last night. The PSC is with me now, and I only take cash."
|
||||
hot.intro.PONERO,"Ransom money, in Ponero. Nobody can trace it. Cash only."
|
||||
hot.offer,"{0} {1}, worth {2} at today's price. Give me {3} in cash and the coins are yours right now."
|
||||
hot.choice.yes,Take it
|
||||
hot.choice.no,Pass
|
||||
hot.say.yes,Deal.
|
||||
hot.say.no,I'm not touching that.
|
||||
hot.done,Coins sent. We never met.
|
||||
hot.refused,Plenty of others will take it.
|
||||
hot.nocash,You can't even put up the cash? Forget it.
|
||||
hot.nowallet,"No wallet connected, so where would the coins go? Forget it."
|
||||
hot.sting,Don't move. Security. Buying stolen funds: the cash is confiscated and this goes on your record.
|
||||
hw.err.poinbase,Poinbase does not accept {0}.
|
||||
@@ -0,0 +1,980 @@
|
||||
# Probably Decentralized localization table: Spanish (es)
|
||||
# AI translation, not proofread. Source: en.csv. Format: key,text (text may be quoted; \n is a line break).
|
||||
upgrade.tab,Web3
|
||||
upgrade.title,Comunidad de gobernanza Web3
|
||||
upgrade.desc,"Los miembros reciben una terminal de comercio, una billetera de hardware, una plataforma de minería, una tarjeta gráfica RTX 60 y una guía de tasación de tarjetas gráficas. La terminal incluye el banco, el exchange Poinbase y las páginas Web3, Minería y Billeteras. El Dr. Jackson vende más tarjetas y plataformas."
|
||||
item.terminal.name,Terminal de comercio
|
||||
item.terminal.desc,"Billetera, exchange Poinbase y reporte nocturno de minería."
|
||||
item.rig.name,Plataforma de minería
|
||||
item.rig.desc,Capacidad: hasta {0} tarjetas gráficas. Tasa de hash: {1} MH/s. Consumo: {2} kJ al día.
|
||||
rig.label.modules,Módulos
|
||||
item.rig.modules,"Módulos: tasa de hash {0}, consumo {1}, desgaste {2}."
|
||||
item.rig.next,Ranura {0}: arrastra {1} a la plataforma de minería ({2}/{3}).
|
||||
mat.common_electronic,Electrónica común
|
||||
mat.rare_electronic,Electrónica rara
|
||||
rig.label.cards,Tarjetas gráficas
|
||||
item.gpu.name,{0} {1}
|
||||
item.gpu.desc,Tasa de hash nominal: {0} MH/s. Consumo nominal: {1} kJ al día. Condición: {2}.
|
||||
item.gpu.burnt.name,{0} {1} quemada
|
||||
item.gpu.burnt.desc,Esta tarjeta ya no funciona.
|
||||
term.title,Terminal de comercio
|
||||
tab.report,Reporte
|
||||
wallet.line,{0}: {1} (aprox. {2} créditos)
|
||||
wallet.empty,La billetera está vacía.
|
||||
wallet.total,Valor total: {0} créditos
|
||||
wallet.taint,Valor contaminado: {0} créditos
|
||||
trade.amount,Cantidad
|
||||
trade.deposit,Depositar créditos como CRC
|
||||
trade.withdraw,Retirar CRC como créditos
|
||||
trade.pair,{0}/{1} ({2})
|
||||
trade.price,Precio {0}
|
||||
trade.buy,Comprar
|
||||
trade.sell,Vender
|
||||
venue.Exchange,Poinbase
|
||||
venue.Dex,DEX
|
||||
venue.Darknet,Darknet
|
||||
msg.amount,Ingresa una cantidad.
|
||||
msg.balance,Saldo insuficiente.
|
||||
msg.trade,Pagado: {0} {1}; recibido: {2} {3}.
|
||||
msg.deposit,Se depositaron {0} créditos como CRC.
|
||||
msg.cashout,Se recibieron {0} créditos. Impuesto: {1} créditos.
|
||||
msg.aml_light,Revisión de cumplimiento: se retuvieron {0} créditos de fondos contaminados.
|
||||
msg.aml_heavy,Revisión de cumplimiento: se confiscaron {0} créditos de fondos contaminados y se reportó a Seguridad.
|
||||
report.none,Aún no hay reporte de minería.
|
||||
report.day,Noche del día {0}
|
||||
report.rigs,Plataformas con energía: {0} de {1}
|
||||
report.hash,Tasa de hash: {0} MH/s (red: {1} MH/s)
|
||||
report.mined,Minado: {0} PSC (aprox. {1} créditos)
|
||||
report.energy,Energía consumida: {0} kJ
|
||||
report.burnt,Tarjetas quemadas: {0}
|
||||
report.price,Precio de PSC: {0} créditos
|
||||
nightlog.mined,Las plataformas de minería produjeron {0} PSC.
|
||||
nightlog.burnt,Se quemó una {0}.
|
||||
coinpay.line,Trato hecho. {0} {1}.
|
||||
nightlog.coinpay,Los pagos de clientes en monedas liquidaron {0} créditos; las monedas fueron a la billetera caliente.
|
||||
nightlog.unpowered,{0} plataforma(s) de minería o minero(s) (máquina) sin energía.
|
||||
news.open.title,Poinbase lista PSC
|
||||
news.open.desc,El exchange Poinbase del Nivel superior ahora lista PSC contra CRC. Aumenta la demanda de tarjetas gráficas en toda la estación.
|
||||
news.halving.title,Halving de recompensa por bloque de PSC
|
||||
news.halving.desc,Los mineros ahora reciben la mitad de monedas por noche.
|
||||
appraisal.gpu,Tarjeta gráfica
|
||||
dealer.name,Camello de hardware usado
|
||||
dealer.line1.1,Tarjetas de una liquidación minera. La condición está escrita junto al nombre.
|
||||
dealer.line1.2,"Unas cuantas tarjetas minadas, salen baratas."
|
||||
dealer.line1.3,Las conseguí en el camino. Precio de primera mano.
|
||||
dealer.line2.1,"Míralas tú mismo, dales la vuelta y revisa el reverso."
|
||||
dealer.line2.2,Sin garantía. Revisa bien antes de llevarte algo.
|
||||
dealer.line2.3,"Si te interesan, el precio es negociable."
|
||||
inspect.flip.back,Ver reverso
|
||||
inspect.flip.front,Ver frente
|
||||
item.gpu.grade.1,como nueva
|
||||
item.gpu.grade.2,aceptable
|
||||
item.gpu.grade.3,claramente desgastada
|
||||
item.gpu.grade.4,muy desgastada
|
||||
point.none.1,No tiene nada malo. Viste mal.
|
||||
point.none.2,"¿Dónde? Si no vas a comprar, no inventes."
|
||||
point.worn.1,"...Está bien, tiene ese detalle. Te hago una rebaja."
|
||||
point.worn.2,"Buen ojo. De acuerdo, te lo dejo a este precio."
|
||||
point.fake.1,...Me descubriste. Está reflasheada. Te la dejo al precio real.
|
||||
point.fake.2,"Tch, no es el chip original. Bien, te cobro el precio del chip real."
|
||||
lbl.fan.0,Aspas limpias
|
||||
lbl.fan.1,Aspas con polvo
|
||||
lbl.fan.2,Aspa mellada
|
||||
lbl.fingers.0,Brillantes
|
||||
lbl.fingers.1,Opacos
|
||||
lbl.fingers.2,Oxidados
|
||||
lbl.print.0,Coincide con el modelo
|
||||
lbl.print.1,Otro modelo impreso
|
||||
lbl.print.2,"Reimpreso, torcido"
|
||||
lbl.said," (el vendedor dijo: {0})"
|
||||
lbl.point,Señalar
|
||||
lbl.edit,Editar
|
||||
cust.fake.1,Eso no es lo que dice la etiqueta. ¿Intentas venderme una falsificación?
|
||||
cust.fake.2,El modelo no coincide. No es el chip que dice ser.
|
||||
cust.worn.1,Eso no fue lo que escribiste. Ocultaste los defectos.
|
||||
cust.worn.2,La condición en la etiqueta es falsa. A este precio no.
|
||||
lbl.row.fan,Aspas
|
||||
lbl.row.fingers,Contactos
|
||||
lbl.row.bracket,Soporte
|
||||
lbl.row.print,Serigrafía trasera
|
||||
lbl.row.serial,Serie
|
||||
lbl.row.seal,Sello
|
||||
lbl.bracket.0,Intacto
|
||||
lbl.bracket.1,Rayado
|
||||
lbl.serial.0,Válido
|
||||
lbl.serial.1,Código de fábrica o longitud inválidos
|
||||
lbl.serial.2,Código de modelo no coincide
|
||||
lbl.seal.0,Intacto
|
||||
lbl.seal.2,Ausente
|
||||
item.guide.name,Guía de tasación de tarjetas gráficas
|
||||
item.guide.desc,Una guía para reconocer tarjetas gráficas falsificadas y determinar su valor.
|
||||
lbl.row.spec,Modelo
|
||||
news.prehalving.title,Halving de PSC inminente
|
||||
news.prehalving.desc,"En tres días, los mineros recibirán la mitad de monedas por noche. Los poseedores esperan que el precio suba."
|
||||
tab.home,Inicio
|
||||
tab.bank,Banco
|
||||
tab.poinbase,Poinbase
|
||||
tab.web3,Web3
|
||||
home.enter,Entrar
|
||||
home.open,Abrir
|
||||
home.summary,Créditos {0} | Activos en cadena: aprox. {1} créditos
|
||||
home.lastnight,"Noche del día {0}: {1} PSC minados, {2} / {3} plataformas con energía"
|
||||
entry.bank,Banco
|
||||
entry.bank.l1,"Depósitos, retiros, renta"
|
||||
entry.bank.l2,Créditos {0}
|
||||
entry.poinbase,Poinbase
|
||||
entry.poinbase.l1,Exchange regulado
|
||||
entry.poinbase.l2,PSC {0} créditos
|
||||
entry.web3,Web3
|
||||
entry.web3.l2,Aprox. {0} créditos
|
||||
entry.help,Ayuda
|
||||
entry.help.l1,Manual de Web3
|
||||
bank.cash,Créditos: {0}
|
||||
bank.rent,"Renta: {0} créditos, vence en {1} día(s)"
|
||||
bank.crc,Cuenta de Poinbase (CRC): {0}
|
||||
poin.account,"Cuenta de Poinbase: CRC {0}, PSC {1}"
|
||||
avg.line,Precio promedio de compra de {0}: {1} créditos
|
||||
avg.short,Prom. compra {0}
|
||||
avg.none,—
|
||||
col.asset,Activo
|
||||
col.amount,Cantidad
|
||||
col.value,Valor
|
||||
col.avg,Prom. compra
|
||||
bank.cash.k,Créditos
|
||||
bank.rent.k,Renta
|
||||
bank.rent.v,"{0}, vence en {1} día(s)"
|
||||
bank.crc.k,Cuenta de Poinbase (CRC)
|
||||
poin.account.h,Cuenta de Poinbase
|
||||
trade.h,Comercio
|
||||
web3.wallet.h,Billetera en cadena
|
||||
stable.ok,Anclado
|
||||
stable.depeg,Desanclado
|
||||
stable.warn,Advertencia: cobertura de reserva del staking baja
|
||||
stable.spiral,En colapso
|
||||
aml.taint,Porcentaje de contaminación de la cuenta: {0}%
|
||||
mixer.h,Mezclador
|
||||
mixer.ok,Estado: en funcionamiento normal
|
||||
mixer.sanctioned,Estado: sancionado (días restantes: {0}). Las monedas retiradas mientras tanto se marcarán.
|
||||
mixer.pending,Depósitos pendientes
|
||||
mixer.none,No hay depósitos pendientes.
|
||||
mixer.col.taint,Contaminación
|
||||
mixer.col.ready,Listo
|
||||
mixer.day,Día {0}
|
||||
mixer.deposit,Depósito
|
||||
mixer.balance,Saldo: {1} {0}
|
||||
mixer.rounds,Rondas
|
||||
mixer.preview,"Retorno previsto: {0} {1}, contaminación reducida ~{2}%, listo el día {3}."
|
||||
mixer.go,Depositar en el mezclador
|
||||
mixer.min,Los depósitos deben valer al menos {0} créditos.
|
||||
mixer.done,Se depositaron {0} {1}; retorno el día {2}.
|
||||
mixer.upgrade.title,Mezclador
|
||||
mixer.upgrade.desc,"Desbloquea el mezclador en la página Red gris de la terminal: deposita monedas contaminadas y recupéralas días después con menos contaminación. El retiro de monedas recién mezcladas pasa por una revisión más estricta; durante las represiones, el mezclador puede ser sancionado y las monedas retiradas mientras tanto quedarán marcadas."
|
||||
news.sanction.title,Mezclador incluido en la lista de sanciones
|
||||
news.sanction.desc,Seguridad sancionó un lote de servicios de mezcla. Los fondos retirados de mezcladores en los próximos días se tratarán como sospechosos.
|
||||
nightlog.mixer,El mezclador devolvió {0} {1}; contaminación {2} -> {3}.
|
||||
nightlog.mixer_flag," (retirado durante las sanciones; dirección marcada)"
|
||||
nightlog.mixer_rug,El operador del mezclador se fugó con el dinero: {0} {1} nunca regresaron.
|
||||
web3.sub.trade,Comercio
|
||||
gray.sub.mixer,Mezclador
|
||||
msg.frozen,Esas monedas están congeladas hasta su descongelación.
|
||||
wallet.frozen,"{0}: {1} congelado, se descongela el día {2}"
|
||||
nightlog.crt_freeze,El mercado negro entregó direcciones durante la represión: {0} de tu CRT está congelado hasta el día {1}.
|
||||
nightlog.thaw,Los {0} {1} congelados se han descongelado.
|
||||
news.crtfreeze.title,El mercado negro congela algunas direcciones de CRT ante la represión
|
||||
news.crtfreeze.desc,Se rumorea que el mercado negro entregó una lista de direcciones de CRT a Seguridad a cambio de inmunidad. Quienes tengan baja reputación son más propensos a ser congelados.
|
||||
black.upgrade.title,Tienda Web3
|
||||
black.upgrade.desc,"Desbloquea la tienda en la página Red gris de la terminal: el brazo en cadena del mercado negro. Surtido semanal de contrabando, ocasionalmente artículos de alta tecnología y tarjetas gráficas (con sobreprecio); compra al contado o haz pedidos y espera al mensajero. Solo monedas (PSC, CRT, CRA, Ponero), se aceptan monedas contaminadas. Requiere reputación con el mercado negro; fuera de servicio durante represiones."
|
||||
black.offline,El acceso en cadena a la tienda está fuera de servicio durante la represión.
|
||||
black.closed,Necesitas una reputación de {0} con el mercado negro para entrar a la tienda (actual: {1}).
|
||||
black.sub.buy,Comprar
|
||||
black.shop.h,Mostrador al contado
|
||||
black.rep,Reputación en el mercado negro: {0}
|
||||
black.empty,Agotado por esta semana.
|
||||
black.offer,{0} x{1} {2} créditos
|
||||
black.buy,Comprar
|
||||
black.bought,Trato cerrado: {0} está en el almacén.
|
||||
black.pay.h,Pago
|
||||
black.desk.h,Mostrador de Ponero
|
||||
black.desk.left,Disponible hoy: {0} (límite {1})
|
||||
black.desk.price,Precio de Ponero: {0}
|
||||
black.desk.swap,Canjear
|
||||
black.desk.in,A Ponero
|
||||
black.desk.out,Desde Ponero
|
||||
black.desk.go,Canjear
|
||||
black.desk.fail,"Error en el canje: saldo, límite o cantidad incorrectos."
|
||||
black.sub.orders,Pedidos
|
||||
black.rugged,La plataforma cayó; nadie reabrirá durante {0} día(s) más.
|
||||
black.seller,"Operaciones: {1}, {2}% positivo"
|
||||
black.orders.h,Catálogo de pedidos
|
||||
black.order,Hacer pedido
|
||||
black.mode.Escrow,Depósito de garantía
|
||||
black.mode.Advance,Liberación anticipada
|
||||
black.ordered,"Pedido realizado: {0}, entrega el día {1}."
|
||||
black.mine.h,Mis pedidos
|
||||
black.mine.none,Aún no hay pedidos.
|
||||
black.mine.line,"{0} ({1}, {2}): {3}, día {4}"
|
||||
black.state.Pending,en tránsito
|
||||
black.state.Ready,en destino
|
||||
black.state.Done,retirado
|
||||
black.state.Refunded.scam,"el vendedor huyó, reembolsado"
|
||||
black.state.Lost.scam,"el vendedor huyó, fondos perdidos"
|
||||
black.state.Lost.rug,"la plataforma hizo rug pull, fondos perdidos"
|
||||
black.state.Lost.intercept,interceptado
|
||||
black.forum.h,Información del foro
|
||||
black.forum.quiet,Todo tranquilo últimamente.
|
||||
black.forum.scam,Dicen que {0} toma el dinero y nunca envía nada.
|
||||
black.forum.rug,"Los retiros han sido lentos últimamente, el sitio tiene promociones y se borraron muchos hilos de quejas."
|
||||
nightlog.bm.scam_refund,Mercado negro: el vendedor {0} huyó; se reembolsó el depósito de garantía de {1}.
|
||||
nightlog.bm.scam_loss,Mercado negro: el vendedor {0} cobró el anticipo y huyó; {1} se perdió ({2} créditos).
|
||||
nightlog.bm.intercept,Mercado negro: se interceptó el paquete con {0}; se perdieron {1} créditos de pago.
|
||||
nightlog.bm.rug,Mercado negro: la plataforma hizo rug pull; los fondos en tránsito de {0} ({1}) se perdieron.
|
||||
nightlog.bm.reopen,Mercado negro: alguien reabrió en el viejo lugar.
|
||||
news.bmrug.title,Plataforma del mercado negro hizo rug pull
|
||||
news.bmrug.desc,"El acceso en cadena al mercado negro cayó de la noche a la mañana, y se esfumaron todos los fondos de depósito de garantía y liberación anticipada. Habrá un nuevo acceso en pocos días."
|
||||
courier.name,Mensajero
|
||||
courier.line1.1,Llegó la entrega.
|
||||
courier.line1.2,Paquete para ti.
|
||||
courier.line2.1,No me digas qué hay dentro. No quiero saberlo.
|
||||
courier.line2.2,Lo dejé aquí. Me voy.
|
||||
gray.sub.black,Tienda
|
||||
black.stock,Restantes: {0}
|
||||
black.price,{0} créditos
|
||||
black.noadvance,Sin liberación anticipada
|
||||
black.kind.gpu,GPU condición {0}%
|
||||
black.kind.Contraband.1,Contrabando (bajo)
|
||||
black.kind.Contraband.2,Contrabando (medio)
|
||||
black.kind.Contraband.3,Contrabando (alto)
|
||||
black.kind.Tech,Alta tecnología (con sobreprecio)
|
||||
nightlog.bm.ready,Mercado negro: {0} ha llegado; un mensajero pasará en cuanto abras.
|
||||
guide.web3.title,Manual de Web3
|
||||
guide.web3.text,"Banco y comercio: la página del banco es de solo lectura y muestra efectivo, alquiler y el CRC de la cuenta de Poinbase. La página Fondos de Poinbase gestiona depósitos y retiros; primero se elige la moneda: el CRC puede ir por la cuenta bancaria o la billetera, las demás monedas solo por la billetera. Depositar desde el banco convierte créditos en CRC en tu cuenta de Poinbase; retirar al banco convierte CRC nuevamente en créditos y pasa por una revisión de cumplimiento que evalúa la contaminación de la cuenta de Poinbase. Retirar a una billetera exige la dirección de destino y varias confirmaciones hasta acreditarse; la comisión de gas es fija, nivel normal, y se descuenta de la moneda enviada. Si el formato de la dirección o el dígito de control es incorrecto, se rechaza; si el formato es válido pero nadie usa esa dirección, las monedas enviadas se pierden.¶Comercio: PSC significa Probably Stolen Coin, la moneda minada por tarjetas gráficas y mineros (máquinas). El mercado spot de Poinbase tiene dos pares, PSC/CRC y SPARK/CRC, según la moneda elegida en el gráfico. Tanto las compras como las ventas se introducen como cantidad de la moneda negociada; la vista previa muestra la moneda de cotización pagada o recibida, el precio medio incluye la comisión y el deslizamiento no.¶La página de comercio de Web3 permite intercambiar cualquier par de monedas, siempre a través de CRC: si CRC está en un extremo se usa un fondo, si no, dos fondos, con dos comisiones y deslizamiento acumulado; la vista previa muestra la cantidad obtenida, los fondos recorridos y la pérdida. Los canjes entre stablecoins (CRT o CRA contra CRC) usan fondos estables: comisión de {StableFee:%} y casi sin deslizamiento cerca de la paridad; durante una pérdida de paridad la liquidez se reduce, y en un colapso se retira y el deslizamiento se dispara.§Billeteras de hardware: las monedas en cadena residen en billeteras de hardware PLEDGER, cada una con sus propios saldos y contaminación. Una billetera es un objeto: arrástrala a la terminal de comercio para cargarla. Ábrela en la página Billeteras de la terminal; conéctala y desconéctala arriba a la derecha de la terminal. El comercio de la página Web3, la tienda y el mezclador de la página Red gris usan la billetera conectada; sin billetera o sin conexión, son solo de lectura y todos los saldos marcan 0. Los clientes que pagan con monedas pagan a la billetera conectada.¶Los pagos (tienda, mezclador, mostrador de Ponero, tarifas de publicación) comienzan como una factura en la terminal; ingresa la dirección del destinatario en la billetera y mantén presionado ✓ para firmar. Los dos últimos caracteres de una dirección son una suma de verificación, por lo que un error tipográfico de un carácter suele detectarse; de vez en cuando resulta válido y las monedas van a una dirección que nadie usa. Los intercambios en DEX también requieren firmar en la billetera.¶Poinbase es una cuenta de custodia; los depósitos se envían desde la billetera a la dirección de depósito de Poinbase (solo PSC, CRC y SPARK; la plataforma regulada no acepta el CRT del mercado negro ni el CRA de la Revolución, y la billetera bloquea su envío a la dirección de depósito) y los retiros se inician en la página Fondos de Poinbase. El Explorador de la página Billeteras permite consultar transferencias por dirección y solo muestra transferencias realmente ocurridas: cada entrada y salida de tus billeteras (transferencias, canjes en DEX y otras llamadas a contratos, ingresos de mineros, retiros, monedas que otros te envían); Ponero es una moneda de privacidad y nunca aparece. El Dr. Jackson vende más billeteras de hardware; arrastra una a la terminal de comercio para agregarla, hasta {WalletMax}. La tienda tiene opciones más baratas. Una billetera que ya no desees puede destruirse en la página Billeteras; sus monedas se pierden para siempre, y todo lo que se envíe después a su dirección también.¶Las transferencias pagan una comisión de gas: lenta, normal o rápida, y los precios del gas suben y bajan en aproximadamente una semana; cuando la red se congestiona, las comisiones de gas suben y las transacciones lentas pueden ser descartadas del mempool. Verifica la dirección completa antes de enviar.§Staking: el CRA en staking en el fondo de la Revolución genera una tasa diaria que se capitaliza en el monto; retirar implica solicitarlo primero y esperar cuatro días, sin intereses durante la espera y sin forma de retirarlo antes. CRA está parcialmente colateralizado: cada CRA está respaldado por la reserva de CRC de la Revolución y por el token de balance SPARK; la cobertura de la reserva y la tasa de colateralización aparecen en la página de staking. Los intereses se pagan con CRA nuevo sin colateral, lo que diluye la cobertura de la reserva, más rápido cuanto más staking haya; si la cobertura es demasiado baja, la Revolución recorta la Line truncated
|
||||
courier.odd1,...Llegó el paquete.
|
||||
courier.odd2,(Mantiene la mano en el bolsillo). Firma aquí.
|
||||
courier.sign,Firmar
|
||||
courier.refuse,Rechazar
|
||||
courier.signed,"Bien. No te muevas, Seguridad."
|
||||
courier.refused,"...Bien, olvídalo."
|
||||
black.state.Lost.seized,incautado
|
||||
black.state.Lost.refused,rechazado
|
||||
black.forum.easy,Demasiado bien últimamente: los vendedores envían más rápido que nunca y hay cuentas nuevas que nadie ha visto.
|
||||
black.forum.busted,Dicen que arrestaron a {0} y los registros de pedidos siguen por ahí.
|
||||
nightlog.bm.trap.honeypot,"Mercado negro: las autoridades intervinieron la plataforma; tu {0} fue rastreado, delito registrado: {1}."
|
||||
nightlog.bm.trap.seller,"Mercado negro: arrestaron a un vendedor y los registros de pedidos te implican: {0}, delito registrado: {1}."
|
||||
tab.mining,Minería
|
||||
courier.sign.say,Firmo.
|
||||
courier.refuse.say,No lo acepto. Devuélvelo.
|
||||
black.forum.busted_buyer,Dicen que arrestaron a un grupo de compradores y los registros de ventas siguen en la plataforma.
|
||||
nightlog.bm.sale_sold,Mercado negro: se vendió tu {0} por {1}; pago el día {2}.
|
||||
nightlog.bm.sale_paid,"Mercado negro: llegó el pago de {1} por {0} (CRT), contaminación {2}."
|
||||
nightlog.bm.sale_fake,Mercado negro: el comprador descubrió que {0} es falso y lo devolvió; tu calificación bajó.
|
||||
nightlog.bm.sale_rug,Mercado negro: la plataforma hizo un rug pull; tu {0} y el pago ({1}) desaparecieron.
|
||||
black.sub.sell,Vender
|
||||
black.sell.h,Venta
|
||||
black.sell.mult,Multiplicador de precio
|
||||
black.sell.none,No hay nada vendible en el almacén.
|
||||
black.sell.rating,Calificación {0}%
|
||||
black.mine.sale,{0} ref {1} precio {2} (x{3}): {4}
|
||||
black.sale.Listed,publicado
|
||||
black.sale.Paid,pagado
|
||||
black.sale.Lost,"rug pull en plataforma, perdido"
|
||||
black.sale.Delisted,retirado
|
||||
black.sale.Delisted.fake,el comprador detectó la falsificación y lo devolvió
|
||||
black.kind.gpunew,GPU nueva
|
||||
merchant.GpuNew,GPU nuevas
|
||||
merchant.GpuUsed,GPU usadas
|
||||
merchant.Arms,Armas
|
||||
merchant.Docs,Tarjetas y chips
|
||||
merchant.Pharma,Fármacos
|
||||
merchant.Bulk,A granel
|
||||
black.days,Entrega en {0} d
|
||||
black.sell.listedall,Artículos publicados: {0}.
|
||||
merchant.Rigs,Plataformas y energía
|
||||
merchant.Modules,Módulos
|
||||
merchant.GunMods,Piezas de armero
|
||||
merchant.Chem,Químicos
|
||||
merchant.Brewer,Destilería
|
||||
merchant.Farm,Hidroponía
|
||||
merchant.Husbandry,Ganadería
|
||||
merchant.Miner,Suministros de minería
|
||||
merchant.Water,Agua
|
||||
merchant.Storage,Almacenamiento
|
||||
merchant.Tools,Herramientas
|
||||
merchant.Luxury,Lujo
|
||||
black.kind.Goods,Mercancías
|
||||
merchant.Elite,Tienda de élite
|
||||
merchant.Personal,Vendedor particular
|
||||
black.pay.confirm,Factura
|
||||
black.pay.to,Dirección del destinatario: {0}
|
||||
black.pay.cancel,Anular
|
||||
pay.mix,Mezclador {0} {1}
|
||||
pay.swap,Mostrador de Ponero {0} {1}
|
||||
black.edit.cancel,Cancelar
|
||||
merchant.Platform,Plataforma
|
||||
black.platform.line,Spot de plataforma entrega inmediata
|
||||
black.orders.in,Comprado
|
||||
black.orders.out,En venta
|
||||
black.desk.pair,PONERO [moneda de privacidad] precio {0}
|
||||
black.pay.amount,Cantidad: {0} {1} (aprox. {2} créditos)
|
||||
black.pay.wallet,Pagar desde billetera
|
||||
hw.total,Total ≈ {0} créditos
|
||||
hw.pending.bill,Por pagar: {0}
|
||||
hw.pending.sign,Por firmar: {0}
|
||||
hw.send,Enviar
|
||||
hw.review,Solicitud de firma
|
||||
hw.to,Dirección del destinatario
|
||||
hw.avail,Disponible {1} {0}
|
||||
hw.amount,Cantidad
|
||||
hw.bill,Factura: {0} {1} {2}
|
||||
hw.fill,Usar monto de la factura
|
||||
hw.next,✓ Siguiente × Atrás
|
||||
hw.err.format,Formato de dirección inválido.
|
||||
hw.err.checksum,Error en la suma de verificación de la dirección.
|
||||
hw.err.self,Es la dirección de esta misma billetera.
|
||||
hw.err.asset,La factura requiere {0}.
|
||||
hw.err.short,Inferior a la factura: {0} {1}.
|
||||
hw.err.nobill,No hay facturas pendientes para este destinatario.
|
||||
hw.review.h,Revisar
|
||||
hw.contract,Llamada de contrato
|
||||
hw.review.to,Dirección del destinatario
|
||||
hw.review.amount,{0} {1} (aprox. {2} créditos)
|
||||
hw.review.bill,Factura: {0}
|
||||
hw.review.unknown,Sin historial de transacciones en esta dirección.
|
||||
hw.review.over,Pago excesivo de {0} {1}; no reembolsable.
|
||||
hw.hold,Mantener ✓ para firmar × Rechazar
|
||||
hw.tx.h,Transacción
|
||||
hw.tx.signing,Firmando…
|
||||
hw.tx.mempool,Transmitida; esperando en la mempool…
|
||||
hw.tx.packed,Incluida en el bloque #{0}
|
||||
hw.tx.confirm,Bloque #{0} confirmación {1}/{2}
|
||||
hw.skip,Omitir
|
||||
hw.done.h,Confirmada
|
||||
hw.done.block,Bloque #{0}
|
||||
hw.done.sent,{0} {1} → {2}
|
||||
hw.done.void,Nadie usa esta dirección. Las monedas se han perdido.
|
||||
hw.back,Volver
|
||||
hw.rejected,Firma rechazada en la billetera.
|
||||
hw.wait,Confirma en la billetera.
|
||||
hw.swap,Canjear {0} {1} → aprox. {2} {3}
|
||||
tab.wallets,Billeteras
|
||||
hw.wallet.n,Billetera {0}
|
||||
hw.review.own,Billetera propia: {0}
|
||||
hw.review.poinbase,Dirección de depósito de Poinbase
|
||||
poin.deposit,Dirección de depósito: {0}
|
||||
wallets.count,Billeteras {0}/{1}
|
||||
wallets.col.name,Nombre
|
||||
wallets.col.addr,Dirección
|
||||
wallets.col.taint,Contaminación
|
||||
wallets.open,Abrir
|
||||
wallets.use,Conectar
|
||||
wallets.current,Conectada
|
||||
wallets.added,Se agregó {0}: {1}
|
||||
nightlog.drained,"Las monedas en {0} fueron transferidas sin autorización, aprox. {1} créditos."
|
||||
item.hwwallet.name,Billetera de hardware PLEDGER
|
||||
item.hwwallet.desc,Billetera de hardware con pantalla grande. Arrástrala a la terminal de comercio para agregar una billetera (máx. 5).
|
||||
poin.empty,La cuenta está vacía.
|
||||
hw.copy,Copiar
|
||||
hw.paste,Pegar
|
||||
hw.copied,Dirección copiada.
|
||||
hw.copied.addr,Copiado: {0}
|
||||
hw.balance.frozen," (congelado: {0})"
|
||||
wallets.destroy,Destruir
|
||||
wallets.destroy.sure,Confirmar
|
||||
wallets.destroyed,Se destruyó {0}: {1}
|
||||
wallets.destroy.warn,Destruir {0} pierde sus monedas para siempre. Pulsa de nuevo para confirmar.
|
||||
payout.label,Pago
|
||||
payout.unset,Sin definir
|
||||
payout.set,Definir dirección
|
||||
payout.h,Dirección de pago
|
||||
payout.cur,Actual: {0}
|
||||
payout.pick,Billeteras propias:
|
||||
payout.manual,O introduce una dirección:
|
||||
payout.clear,Borrar
|
||||
payout.err,Dirección no válida.
|
||||
nightlog.mined.lost,"Se perdieron {0} PSC minados: sin dirección de pago definida, o su billetera fue destruida."
|
||||
wallets.none,Ninguna billetera cargada. Arrastra una billetera de hardware a la terminal.
|
||||
web3.err.noconn,Ninguna billetera conectada.
|
||||
web3.connect,Conectar billetera
|
||||
web3.disconnect,Desconectar
|
||||
web3.conn,{0} {1}
|
||||
hw.balance.value,≈ {0}
|
||||
wallets.rename,Renombrar
|
||||
wallets.rename.h,Nuevo nombre para {0}
|
||||
wallets.rename.ok,Aceptar
|
||||
hw.fee.slow,Lento
|
||||
hw.fee.normal,Normal
|
||||
hw.fee.fast,Rápido
|
||||
hw.fee,Comisión de gas {0} {1} (aprox. {2} créditos)
|
||||
hw.confs,Confirmaciones requeridas: {0}
|
||||
hw.congested,Red congestionada
|
||||
hw.congested.slow,Red congestionada: la tarifa lenta podría ser descartada de la mempool
|
||||
hw.recent,Reciente
|
||||
hw.recent.out,→ {0} {1} {2}
|
||||
hw.recent.in,← {0} {1} {2}
|
||||
hw.review.history,Dirección en tu historial
|
||||
hw.tx.stuck,En cola en la mempool…
|
||||
hw.tx.dropped,Descartada de la mempool. No se envió nada; la comisión de gas igual se cobró.
|
||||
hw.dropped.h,No enviado
|
||||
hw.err.fee,Saldo insuficiente para cubrir la comisión de gas.
|
||||
news.congest.title,Congestión en la red
|
||||
news.congest.desc,Una avalancha de airdrops ha saturado la red. Las comisiones de gas se multiplicaron y las transacciones de comisión baja podrían ser descartadas de la mempool.
|
||||
news.phish.title,Aviso de Poinbase: migración de direcciones de depósito
|
||||
news.phish.desc,"Poinbase actualizó su sistema de billeteras. La dirección de depósito anterior será retirada; por favor, envía los activos a la nueva dirección {0}."
|
||||
black.forum.phish,"Alguien publicó la nueva dirección del mezclador: {0}, diciendo que la anterior está vigilada."
|
||||
hw.gas,Gas ×{0}
|
||||
web3.sub.stake,Staking
|
||||
stake.h,Fondo de staking de la Revolución
|
||||
stake.rate,Tasa diaria {0}%; el retiro tarda {1} día(s) sin generar interés
|
||||
stake.low,Cobertura de reserva baja; tasa reducida
|
||||
stake.cra,Precio de CRA {0} {1}
|
||||
stake.none,Nada en staking.
|
||||
stake.col.wallet,Billetera
|
||||
stake.col.amount,En staking
|
||||
stake.col.queue,Desbloqueo
|
||||
stake.day," (día {0})"
|
||||
spark.price,Token de balance SPARK {0} créditos
|
||||
stake.ops,{0}
|
||||
stake.avail,CRA {0} En staking {1}
|
||||
stake.do,Hacer staking
|
||||
stake.undo,Solicitar retiro
|
||||
stake.sum.in,Poner {0} CRA en staking
|
||||
stake.sum.out,Solicitar retiro de {0} CRA (llega en {1} día(s))
|
||||
stake.done.in,{0} CRA puestos en staking.
|
||||
stake.done.out,Retiro de {0} CRA solicitado; vuelve a la billetera el día {1}.
|
||||
nightlog.stakeint,Interés de staking +{0} CRA.
|
||||
nightlog.unstaked,Los {0} CRA retirados de staking volvieron a {1}.
|
||||
news.crawarn.title,Agitación en el fondo de staking de la Revolución
|
||||
news.cralow.title,La Revolución reduce la tasa de staking
|
||||
stake.avail2,SPARK {0}
|
||||
poin.sub.spot,Spot
|
||||
poin.sub.perp,Perpetuos
|
||||
perp.h,Futuros perpetuos
|
||||
perp.acct,Cuenta de margen CRC {0}
|
||||
perp.debt,Deuda {0}; los bienes se incautan en {1} día(s). Sin nuevas posiciones ni retiros hasta saldarla.
|
||||
perp.banned,Cuenta de perpetuos suspendida {0} día(s) más.
|
||||
perp.none,Sin posiciones.
|
||||
perp.col.pos,Posición
|
||||
perp.col.notional,Valor nocional
|
||||
perp.col.price,Entrada → precio
|
||||
perp.col.pnl,PnL
|
||||
perp.col.liq,Precio liq.
|
||||
perp.long,Largo
|
||||
perp.short,Corto
|
||||
perp.rate,{0} precio {1} financiación {2}%/noche
|
||||
perp.fund,Fondo de seguro {0}
|
||||
perp.open,Abrir
|
||||
perp.margin,Cantidad de margen (CRC)
|
||||
perp.do.open,Abrir
|
||||
perp.do.add,+ Margen
|
||||
perp.do.close,Cerrar
|
||||
perp.opened,"Se abrió {0} {1}: margen {2} CRC, {3}×."
|
||||
perp.added,Se agregaron {0} CRC de margen.
|
||||
perp.closed,Cerrada; {0} CRC de vuelta en la cuenta (PnL {1}).
|
||||
perp.deficit,"El capital fue insuficiente por {0}, cubierto por el fondo de seguro y deuda."
|
||||
perp.err.Banned,La cuenta de perpetuos está suspendida.
|
||||
perp.err.Debt,Tienes deudas pendientes; no se permiten nuevas posiciones.
|
||||
perp.err.Leverage,El apalancamiento supera el límite de este producto.
|
||||
perp.err.Size,Supera el límite de posición de este producto.
|
||||
perp.err.Funds,Saldo de CRC insuficiente en la cuenta (incluye la tarifa).
|
||||
perp.err.Opposite,No puedes tener posiciones largas y cortas en el mismo producto; cierra primero.
|
||||
perp.err.NoPosition,Sin posición.
|
||||
perp.err.Margin,Ingresa una cantidad de margen.
|
||||
perp.debt.block,Tienes deuda en la mesa de perpetuos; retiros bloqueados.
|
||||
nightlog.perp.liq,{0} fue liquidado; se perdió el margen de {1}.
|
||||
nightlog.perp.adl,El fondo de seguro se agotó; {0} sufrió desapalancamiento auto y cedió {1} de ganancias.
|
||||
nightlog.perp.interest,La deuda de perpetuos acumuló intereses; ahora debes {0}.
|
||||
nightlog.perp.seize,Deuda de perpetuos vencida: los objetos confiscados cubrieron {0}.
|
||||
nightlog.perp.writeoff," Se condonaron {0}; la cuenta de perpetuos queda suspendida por {1} día(s)."
|
||||
perp.slip.title,Comprobante de embargo por deuda de perpetuos
|
||||
perp.preview2,Comisión {0} liq. {1}
|
||||
nightlog.perp.repaid,Déficit de perpetuos: se dedujeron {0} CRC de la cuenta de Poinbase para saldarlo.
|
||||
perp.err.Thin,El deslizamiento de esta orden es tan alto que causaría liquidación inmediata. Reduce el tamaño o el apalancamiento.
|
||||
perp.err.Single,Solo una posición a la vez; añade margen.
|
||||
mat.hypertech_electronic,Componente electrónico hipertecnológico
|
||||
item.asic.name,Minero RatDigg {0}
|
||||
item.asic.dead.name,Minero RatDigg {0} quemado
|
||||
item.asic.desc,Tasa de hash nominal: {0} GH/s. Consumo nominal: {1} kJ al día. Condición: {2}. Minero independiente: requiere una batería para operar y admite módulos.
|
||||
item.asic.dead.desc,Quemado. Arrastra componentes electrónicos sobre él para repararlo: requiere {0} × {1}. La salud se reduce en 20 al repararlo.
|
||||
item.asic.dead.fixed,Ya está reparado.
|
||||
merchant.Asic,Camello de mineros
|
||||
black.kind.asic,Minero condición {0}%
|
||||
black.kind.asicnew,Minero nuevo
|
||||
news.erawarn.title,RatDigg está por lanzar una nueva generación de mineros
|
||||
news.erawarn.desc,El fabricante de mineros dedicados anunció nuevo hardware y la industria prevé que las grandes granjas renueven equipos en masa pronto. Dicen que los días dorados de la minería con GPU están contados.
|
||||
news.era.title,La era de los mineros
|
||||
news.era.desc,Una nueva generación de mineros dedicados entró en producción masiva y las grandes granjas redujeron sus costos de energía a la mitad. La tasa de hash de la red subirá y las ganancias de los mineros con GPU se diluirán.
|
||||
web3.sub.predict,Predicción
|
||||
predict.h,Mercados de predicción
|
||||
predict.acct,{0}: CRC {1}
|
||||
predict.none,No hay mercados abiertos hoy.
|
||||
predict.closed,cerrado
|
||||
predict.row,Sí {0} No {1}
|
||||
predict.held,"tienes {0} x{1}, costo {2}"
|
||||
predict.yes,Sí
|
||||
predict.no,No
|
||||
predict.void,anulado
|
||||
predict.result,Día {0} {1} resultado: {2} {3}
|
||||
predict.pick,Operar
|
||||
predict.price,Precio por acción: Sí {0} No {1}
|
||||
predict.pos,{0}: {1} x{2}
|
||||
predict.pos2,Costo {0} paga {1}
|
||||
predict.sum.buy,Comprar {1} por {2} CRC: {0}
|
||||
predict.sum.sell,Vender posición de predicción: {0}
|
||||
predict.closed.note,"Cerrado, en espera de liquidación."
|
||||
predict.preview,"Comprar {0}: aprox. {1} acciones (prom. {2}), neto {3} si aciertas"
|
||||
predict.buy.yes,Comprar Sí
|
||||
predict.buy.no,Comprar No
|
||||
predict.sell,Vender todo
|
||||
predict.bought,Compraste {0} por {2}; paga {1} si aciertas.
|
||||
predict.sold,Vendido; recibiste {0}.
|
||||
predict.err.Closed,Este mercado está cerrado.
|
||||
predict.err.Amount,Cantidad no válida.
|
||||
predict.err.Funds,No hay suficiente CRC en la billetera.
|
||||
predict.err.Cap,Se superó el límite de posición de este mercado.
|
||||
predict.err.Opposite,Ya tienes la posición contraria; véndela primero.
|
||||
predict.err.NoPosition,No tienes posiciones en este mercado.
|
||||
predict.win.one,Día {0}
|
||||
predict.win.range,Días {0}-{1}
|
||||
predict.q.event,"{0}: ocurre ""{1}"""
|
||||
predict.q.faction,{0}: {1} inicia una operación
|
||||
predict.q.purity,{0}: pureza de {1} >= {2}
|
||||
predict.q.price,{0}: precio de {1} >= {2}
|
||||
predict.faction.FACTION_SECURITY,Seguridad
|
||||
predict.faction.FACTION_REVOLUTION,Revolución
|
||||
predict.faction.FACTION_LOWER_LEVEL,Nivel inferior
|
||||
predict.faction.FACTION_UPPER_LEVEL,Nivel superior
|
||||
predict.faction.FACTION_BLACK_MARKET,Mercado negro
|
||||
predict.purity.gutter,Agua del nivel inferior
|
||||
predict.purity.rust,Agua del nivel superior
|
||||
nightlog.predict.win,"Predicción acertada: ""{0}""; se pagaron {1}."
|
||||
nightlog.predict.lose,"Predicción fallida: ""{0}""; perdiste la apuesta de {1}."
|
||||
nightlog.predict.void,"Predicción anulada: ""{0}""; se reembolsó la apuesta de {1}."
|
||||
nightlog.predict.caught,"Apuesta con información privilegiada detectada: ""{0}""; se confiscaron la apuesta y las ganancias por {1}, registro por fraude."
|
||||
predict.tab.markets,Mercados
|
||||
predict.tab.intel,Información
|
||||
predict.acct.crt,{0}: CRT {1}
|
||||
predict.tier.0,bajo
|
||||
predict.tier.1,medio
|
||||
predict.tier.2,alto
|
||||
predict.clue.tip,Pista ({0}): dice {1}
|
||||
predict.clue.queued,Programado: inicia el día {0}
|
||||
predict.clue.queued2,"Programado: día {0} ""{1}"""
|
||||
predict.clue.cool,Evento activo o en enfriamiento
|
||||
predict.clue.busy,Operación de facción en curso; no habrá otra pronto
|
||||
predict.clue.halving,Halving en el día {0}; el ancla sube la semana previa
|
||||
predict.clue.anchor,Ancla de precio actual: {0}
|
||||
predict.clue.gas,Gas reciente: {0}
|
||||
predict.clue.drain,Consumo por noche: {0}
|
||||
predict.clue.era,"Aleatorio entre días {0}-{1}, aviso previo"
|
||||
predict.clue.era.warned,Anunciado: inicia entre días {0}-{1}
|
||||
predict.q.gas,{0}: índice de gas >= {1}
|
||||
predict.q.cra,{0}: advertencia de CRA emitida
|
||||
predict.q.era,{0}: inicia la era ASIC
|
||||
predict.era,Era ASIC
|
||||
predict.pos3,Prom. {0} actual {1}
|
||||
predict.pos4,Vender ahora devuelve {0}
|
||||
intel.h,Traficante de información
|
||||
intel.locked,Requiere la tienda Web3 y reputación en el Mercado negro: {0}.
|
||||
intel.brief.buy,Comprar informe de situación ({0} CRT)
|
||||
intel.brief.none,Aún no se ha comprado ningún informe.
|
||||
intel.brief.day,Informe del día {0}
|
||||
intel.tips.h,Pistas confidenciales
|
||||
intel.tips.none,Nada que consultar (solo operaciones de facción y la era ASIC).
|
||||
intel.tip.buy,Precisión aprox. {0}% {1} CRT
|
||||
intel.err.funds,No hay suficiente CRT en la billetera o el mercado ya no admite compras.
|
||||
intel.brief.sum,"Informe de situación, {0} CRT"
|
||||
intel.tip.sum,Pista confidencial {0} CRT: {1}
|
||||
intel.brief.done,Informe obtenido.
|
||||
intel.tip.done,Dicen: {0}.
|
||||
predict.brief.levels,Seguridad {0} Rev. {1} Merc. negro {2} Disturbios {3} Nivel sup. {4}
|
||||
predict.brief.busy,{0}: operación en curso
|
||||
predict.brief.queued,{0}: operación programada
|
||||
predict.brief.none,{0}: nada que iniciar
|
||||
predict.brief.can,{0}: puede iniciar {1}
|
||||
predict.clue.push,Moviste el precio un {0}%: riesgoso
|
||||
nightlog.predict.manip,"Predicción clasificada como manipulación: ""{0}""; apuesta de {1} confiscada, registro por fraude."
|
||||
news.manip.title,El exchange investiga operaciones inusuales
|
||||
news.manip.desc,Los reguladores informan que alguien manipuló el precio con grandes órdenes al contado para lucrar con derivados y predicciones; los fondos fueron incautados.
|
||||
perp.manip,Ganancia de {0} al cerrar dictaminada como manipulación de precio y confiscada; cuenta de perpetuos congelada por {1} día(s).
|
||||
web3.sub.ponzi,Rendimiento
|
||||
ponzi.h,Esquema Ponzi
|
||||
ponzi.acct,Billetera emisora {0}: CRC {1}
|
||||
ponzi.rate,Tasa diaria {0}%
|
||||
ponzi.pool,Fondo {0} / límite {1}
|
||||
ponzi.inflow,Nuevos depósitos anoche: {0}
|
||||
ponzi.interest,Intereses a pagar esta noche: {0}
|
||||
ponzi.own,Intereses pagados de tu bolsillo: {0}
|
||||
ponzi.wind,Riesgo de denuncia: {0}
|
||||
ponzi.wind.low,bajo
|
||||
ponzi.wind.mid,medio
|
||||
ponzi.wind.high,alto
|
||||
ponzi.idle,Ningún esquema emitido.
|
||||
ponzi.done,El esquema está cerrado; solo uno por partida.
|
||||
ponzi.ops,Acciones
|
||||
ponzi.rug,Hacer rug pull al fondo ({0})
|
||||
ponzi.rug.confirm,Haz clic de nuevo para confirmar el rug pull de {0}
|
||||
ponzi.rugged,"Tomaste {0}, totalmente contaminados."
|
||||
ponzi.open,Crear un esquema
|
||||
ponzi.ad,Costo de publicidad: {0} CRC de la billetera actual; requiere firma.
|
||||
ponzi.start,Lanzar
|
||||
ponzi.started,Lanzado.
|
||||
ponzi.err,No hay suficiente CRC en la billetera para el costo de publicidad.
|
||||
nightlog.ponzi.collapse,"El esquema no pudo pagar intereses; pánico bancario, se confiscaron {0}, registro por fraude y la reputación del nivel inferior quedó en cero."
|
||||
nightlog.ponzi.reported,"El esquema fue denunciado; se confiscaron {0} del fondo, registro por fraude y la reputación del nivel inferior quedó en cero."
|
||||
news.ponzi.title,Colapsa esquema Ponzi
|
||||
news.ponzi.desc,Un esquema Ponzi operado en el nivel inferior fue denunciado; los inversores protestaron y los reguladores congelaron los fondos.
|
||||
news.ponzi.rug.title,Estafa de inversión
|
||||
news.ponzi.rug.desc,El operador de un esquema Ponzi huyó con todos los fondos; los inversores del Nivel inferior lo perdieron todo.
|
||||
ponzi.start.sum,"Iniciar esquema Ponzi, tasa diaria {0}%, publicidad {1} CRC"
|
||||
ponzi.rug.sum,Rug pull del fondo {0}
|
||||
ponzi.err.wallet,Firmar con la billetera emisora.
|
||||
predict.clue.counter,"Información: programada (informante del mostrador, nota de rumores)"
|
||||
web3.sub.airdrop,Airdrops
|
||||
air.h,Airdrops
|
||||
air.none,No hay airdrops para reclamar ahora.
|
||||
air.row,{0} recompensa {1} CRC {2} hasta el día {3}
|
||||
air.claim,Reclamar
|
||||
air.unlimited,aprobar {0} ilimitado
|
||||
air.limited,aprobar {0} {1}
|
||||
air.approvals,Aprobaciones de {0}
|
||||
air.approvals.none,Sin aprobaciones.
|
||||
air.approval,{0}: {1}
|
||||
air.revoke,Revocar
|
||||
air.sum,Reclamar airdrop {0} ({1})
|
||||
air.claimed,Se recibieron {0} CRC.
|
||||
air.auth,Autorizar billetera
|
||||
air.unauth,No autorizado
|
||||
air.authed,Autorizado: {0}
|
||||
air.authed.msg,Billetera autorizada para {0}.
|
||||
air.auth.sum,Autorizar a {0} a actuar por esta billetera. Alcance: {1}.
|
||||
air.err.unauth,Primero autoriza la billetera para este airdrop.
|
||||
air.revoke.sum,Revocar aprobación de {1} para {0}
|
||||
air.revoked,Aprobación revocada.
|
||||
air.err.wallet,Firmar con la billetera que aprobó.
|
||||
pool.h,Fondos de rendimiento de terceros (CRC)
|
||||
pool.none,Ninguno por ahora.
|
||||
pool.col.name,Fondo
|
||||
pool.col.rate,Tasa/día
|
||||
pool.col.reserve,Reserva
|
||||
pool.col.lock,Bloqueo
|
||||
pool.col.audit,Auditoría
|
||||
pool.col.mine,Mi depósito
|
||||
pool.yes,sí
|
||||
pool.no,no
|
||||
pool.pending,retirando
|
||||
pool.closed,(cerrado)
|
||||
pool.deposit,Depósito
|
||||
pool.withdraw,Retiro
|
||||
pool.withdraw.lock,Solicitar retiro ({0} d)
|
||||
pool.err.cap,Supera el límite del fondo; quedan {0}.
|
||||
pool.err.none,Sin depósitos.
|
||||
pool.sum.in,Depósito en {0}: {1} CRC
|
||||
pool.sum.out,Retirar {1} CRC de {0}
|
||||
pool.done.in,Se depositaron {0} CRC en {1}.
|
||||
pool.done.out,Se retiraron {0} CRC.
|
||||
pool.done.lock,Se solicitaron {0} CRC; llegan el día {1}.
|
||||
nightlog.scam.drain,"""{3}"" se llevó {1} {2} de {0} mediante una aprobación."
|
||||
nightlog.scam.rug,"El fondo de rendimiento ""{0}"" hizo rug pull; desaparecieron {1} CRC de {2}."
|
||||
nightlog.scam.dry,"El fondo de rendimiento ""{0}"" se quedó sin reservas y cerró; se devolvieron {1} CRC a {2}."
|
||||
nightlog.scam.paid,"Llegó el retiro de ""{0}"": {2} recibió {1} CRC."
|
||||
nightlog.scam.fakepay,Transferencia falsificada: {0}
|
||||
nightlog.scam.sent,"Los {0} {1} enviados a la dirección segura de ""soporte"" terminaron en manos de un estafador."
|
||||
coinpay.intro,Pagaré con {0}; tarda un momento en confirmarse en la cadena.
|
||||
coinpay.intro.fake,"Ya envié los {0}, aquí está la captura. Dámelo ya, tengo prisa."
|
||||
coinpay.fake.entry,{0} se llevó {1} afirmando haber pagado {2} créditos en monedas; no existe tal transacción en la cadena.
|
||||
scam.support.name,Soporte de Poinbase
|
||||
scam.support.1,"Hola, soporte de Poinbase por aquí. Detectamos un inicio de sesión inusual en tu cuenta y fue marcada."
|
||||
scam.support.2,Envía {0} CRC hoy a la dirección segura {1} para verificación; se devolverá inmediatamente después.
|
||||
scam.support.3,"De lo contrario, la cuenta quedará congelada para siempre. Me tengo que ir, no olvides enviarlo."
|
||||
predict.sold.caught,"Información privilegiada detectada al vender: apuesta y ganancias confiscadas, fraude registrado."
|
||||
predict.row.move," (anoche {0} {1})"
|
||||
predict.stats.h,Historial (precio prom. apertura / tasa real)
|
||||
predict.stats.row,"{0}: {1} mercados, prom. apertura {2}, ocurrió {3}%"
|
||||
predict.kind.Event,Eventos de noticias
|
||||
predict.kind.Faction,Operaciones de facción
|
||||
predict.kind.Purity,Pureza del agua
|
||||
predict.kind.Price,Precio de PSC
|
||||
predict.kind.Gas,Gas
|
||||
predict.kind.Cra,Alerta de CRA
|
||||
predict.kind.Era,Era ASIC
|
||||
nightlog.predict.move,"Predicción ""{0}"" cambió {1} -> {2}"
|
||||
nightlog.predict.why," ({0})"
|
||||
chart.empty,Gráfico diario de {0}: sin historial aún; registrando desde hoy.
|
||||
chart.caption,{0} diario Máx {2} Mín {3} Cierre {4} ({5}%)
|
||||
chart.legend,"<size=80%>verde sube, rojo baja; amarillo MM 7 d; barras: gris mercado / cian tú</size>"
|
||||
chart.legend.thr,"<size=80%>verde sube, rojo baja; amarillo MM 7 d; trazos azules umbral</size>"
|
||||
news.story.serpico_rev.title,La Revolución tiene pruebas contra Seguridad
|
||||
news.story.serpico_rev.desc,"Según se informa, la Revolución obtuvo pruebas de corrupción interna en Seguridad. Novedades del fondo de staking: se inyectó una gran suma a la reserva de la Revolución, y SPARK se ha ido fortaleciendo."
|
||||
news.story.serpico_bm.title,El Mercado negro llega a un acuerdo discreto
|
||||
news.story.serpico_bm.desc,"Un documento interno de Seguridad cambió de manos en el Mercado negro. La liquidación en la Darknet ha sido notablemente más estable desde entonces, y los canjes de CRT no han fallado ni una sola vez."
|
||||
news.story.serpico_sec.title,Seguridad inicia una purga interna
|
||||
news.story.serpico_sec.desc,Seguridad anunció una investigación exhaustiva sobre corrupción interna y mayor control del flujo de dinero. Poinbase endurece la revisión de retiros y se han señalado los servicios de mezcla.
|
||||
news.story.eleanor_leak.title,Se filtran datos de cultivo de nutrifrutas
|
||||
news.story.eleanor_leak.desc,El periódico del Nivel inferior publicó una investigación que permite a la nutrifruta volver a dar semillas; las acciones de Pastelle se desplomaron. El banco custodio de fondos del Nivel superior reporta deudas incobrables y la Revolución gana terreno.
|
||||
news.story.eleanor_return.title,Pastelle recupera datos robados
|
||||
news.story.eleanor_return.desc,Pastelle confirmó que recuperó datos de investigación robados. El capital del Nivel superior respiró con alivio y se elevó la calificación del banco custodio de CRC.
|
||||
news.story.lun_arrested.title,El Agente Lun bajo arresto por abuso de poder
|
||||
news.story.lun_arrested.desc,Seguridad arrestó al Agente Lun en el acto por abuso de poder y prometió mano dura contra el comercio ilegal durante las próximas dos semanas.
|
||||
tumbler.name,Tumbler
|
||||
tumbler.v1.1,Hola. Escuché que la terminal de aquí está conectada a mi mezclador.
|
||||
tumbler.v1.2,Yo creé esa cosa. Me dicen Tumbler.
|
||||
tumbler.v1.3,No toca tu mercancía ni lleva tus cuentas. Solo revuelve las monedas.
|
||||
tumbler.v1.4,Pasaba por aquí. Quería ver qué aspecto tienen mis usuarios.
|
||||
tumbler.v2.1,Las cosas se están poniendo feas. Seguridad va tras los servicios de mezclador en la cadena.
|
||||
tumbler.v2.2,Marcaron un par de direcciones grandes y rastrearon el origen hasta mi nodo.
|
||||
tumbler.v2.3,"Si el mezclador deja de operar unos días, no te asustes. Las monedas adentro no se perderán."
|
||||
tumbler.v3.1,Cerraron mi nodo. Tarde o temprano encontrarán dónde vivo.
|
||||
tumbler.v3.2,Tengo una unidad de claves con las claves de firma del mezclador.
|
||||
tumbler.v3.3,"Si Seguridad la consigue, pueden reconstruir el historial de todos los usuarios. El tuyo también."
|
||||
tumbler.v3.ask,¿Puedes esconderla unos días?
|
||||
tumbler.v3.choice.hide,[Tomar la unidad y esconderla]
|
||||
tumbler.v3.choice.report,[Aceptar y luego dar aviso a Seguridad]
|
||||
tumbler.v3.choice.sell,[Tomar la unidad y venderla al Mercado negro]
|
||||
tumbler.v3.thanks1,Gracias. Volveré por ella en unos días.
|
||||
tumbler.v3.thanks2,"No la dejes a la vista. Si un registro la encuentra, estamos acabados."
|
||||
tumbler.v3.report1,...De acuerdo. Pasaré más tarde.
|
||||
tumbler.v4.back.1,Vengo por la unidad.
|
||||
tumbler.v4.back.2,El nodo se mudó a otro lugar. Seguridad no lo encontrará pronto.
|
||||
tumbler.v4.back.3,"Toma esto por las molestias. De ahora en adelante, las tarifas de mi mezclador son a mitad de precio."
|
||||
tumbler.v4.lost.1,¿Dónde está la unidad?
|
||||
tumbler.v4.lost.2,...¿La perdiste?
|
||||
tumbler.v4.lost.3,Olvídalo. Ya veré qué hago.
|
||||
tumbler.v4.sold.1,"Le vendiste la unidad al Mercado negro, ¿verdad?"
|
||||
tumbler.v4.sold.2,Ahora ellos controlan el mezclador. Las tarifas se duplicaron y el dinero de los usuarios podría desaparecer cualquier día.
|
||||
tumbler.v4.sold.3,No olvidaré esto.
|
||||
tumbler.v4.none.1,Olvídalo. Yo nunca estuve aquí.
|
||||
item.keydrive.name,Unidad de claves
|
||||
item.keydrive.desc,"Una memoria que te dejó Tumbler con las claves de firma del mezclador. Contrabando: si un registro la encuentra, quedará en tu expediente."
|
||||
mixer.closed,El mezclador se cerró y no acepta nuevos depósitos. Las monedas que ya están dentro se devuelven como de costumbre.
|
||||
news.tumbler.sanction.title,Seguridad incauta nodo de mezcla
|
||||
news.tumbler.sanction.desc,"Seguridad anunció la incautación de un nodo de un servicio de mezcla en cadena, afirmando que facilitaba el lavado de dinero. El servicio está temporalmente suspendido."
|
||||
news.tumbler.caught.title,Operador del mezclador bajo arresto
|
||||
news.tumbler.caught.desc,El operador del mezclador conocido como Tumbler fue arrestado en el nivel inferior. Seguridad afirma que el servicio de mezcla ha sido cerrado definitivamente.
|
||||
news.tumbler.sold.title,Servicio de mezcla cambia de manos
|
||||
news.tumbler.sold.desc,Se dice que las claves de firma de un servicio de mezcla del nivel inferior han caído en manos del mercado negro y las tarifas subieron de inmediato. Los usuarios temen por sus fondos.
|
||||
nightlog.tumbler.gift,Tumbler recuperó la unidad de claves y dejó {0} CRT como agradecimiento (enviados a {1}); las tarifas del mezclador se redujeron a la mitad.
|
||||
mixer.status.closed,Estado: cerrado
|
||||
yield.sub.pools,Fondos de rendimiento
|
||||
yield.sub.mine,Emitir esquema
|
||||
pool.side.h,Depósito
|
||||
ponzi.early,Los esquemas Ponzi se pueden emitir a partir del día {0}.
|
||||
bpay.h,Pago
|
||||
bpay.qty,Cantidad
|
||||
bpay.total,Total en créditos: {0}
|
||||
bpay.need,Pagar {0} {1} saldo en billetera {2}
|
||||
bpay.invoice,Crear factura
|
||||
bpay.swap.h,Autoconversión a {0}
|
||||
bpay.swap.none,No hay otra moneda suficiente en la billetera
|
||||
bpay.swap.need,"Pagar {0} {1}, incluye {2}% de deslizamiento"
|
||||
bpay.swap.btn,Convertir y pagar
|
||||
bpay.swap.sum,"{0}: autoconversión, pagar {2} {1}, cambiado a {3} antes de hacer el pedido"
|
||||
bpay.back,Volver
|
||||
cart.fab,Carrito {0}
|
||||
cart.h,Carrito
|
||||
cart.empty,El carrito está vacío.
|
||||
cart.added,Agregado al carrito: {0}
|
||||
cart.back,Volver a la tienda
|
||||
cart.done,Artículos pagados: {0}.
|
||||
cart.partial,Artículos pagados: {0}; fallidos: {1} (stock o saldo).
|
||||
black.info.accepts,Acepta: {0}
|
||||
black.info.advance.yes,acepta liberación anticipada
|
||||
black.info.advance.no,no acepta liberación anticipada
|
||||
settings.section.ui,Interfaz
|
||||
settings.section.story,Historia
|
||||
settings.section.difficulty,Dificultad
|
||||
settings.terminal_size,Tamaño de la terminal de comercio
|
||||
settings.terminal_size_desc,Tamaño de la ventana en unidades de interfaz (ancho × alto). Se aplica al abrir la terminal de nuevo.
|
||||
settings.tumbler_story,Trama de Tumbler
|
||||
settings.tumbler_story_desc,"Visitas de Tumbler y el encargo del unidad de claves. Desactivada, no habrá visitas nuevas; el progreso logrado se conserva."
|
||||
settings.risk_scale,Multiplicador de riesgo
|
||||
settings.risk_scale_desc,"Multiplica la probabilidad de estafas, rug pulls, envenenamiento de billetera, secuestro de direcciones y phishing. Se aplica a todas las partidas."
|
||||
settings.mining_scale,Multiplicador de recompensa de minería
|
||||
settings.mining_scale_desc,Multiplica la recompensa de bloque que reciben los equipos de minería. Se aplica a todas las partidas.
|
||||
gg.header,Comisión Comercial de la estación
|
||||
gg.p1.cap,Tarjeta gráfica
|
||||
gg.p1.makers,"En la estación hay dos fabricantes habituales:\n\n - Probidia (""PB"")\n - PMD (""MD"")"
|
||||
gg.p1.note,"Sea cual sea el fabricante, el valor de una tarjeta depende solo del precio de lista del chip real y de su salud: con salud completa equivale al precio de lista, con salud 0 solo queda el {CardValueFloor:%}."
|
||||
gg.fan.h,Aspas
|
||||
gg.fan.0,Limpias (precio igual)
|
||||
gg.fan.1,Con polvo (-{CardFanDust:%})
|
||||
gg.fan.2,Melladas (-{CardFanChipped:%})
|
||||
gg.fin.h,Contactos
|
||||
gg.fin.0,Brillantes (precio igual)
|
||||
gg.fin.1,Opacos (-{CardFingersDark:%})
|
||||
gg.fin.2,Oxidados (-{CardFingersOxidized:%})
|
||||
gg.brk.h,Soporte
|
||||
gg.brk.0,Intacto (precio igual)
|
||||
gg.brk.1,Rayado (-{CardBracketScratch:%})
|
||||
gg.seal.h,Sello
|
||||
gg.seal.0,Intacto (precio igual)
|
||||
gg.seal.2,Ausente (-{CardSealMissing:%})
|
||||
gg.wear.note,"Las aspas, los contactos y el soporte empeoran con el desgaste de cada noche y solo pueden ir a peor; el sello es una característica fija. La condición también afecta a la tasa de hash, al desgaste y a la probabilidad de quemarse."
|
||||
gg.serial.h,Número de serie
|
||||
gg.serial.cap,Reverso (pegatina de serie)
|
||||
gg.serial.pb,"Probidia (""PB"")\n Códigos de fábrica válidos: 11, 12, 21, 34, 47"
|
||||
gg.serial.md,"PMD (""MD"")\n Códigos de fábrica válidos: 13, 22, 35, 41, 58"
|
||||
gg.print.h,Serigrafía trasera
|
||||
gg.print.0,Coincide con el modelo
|
||||
gg.print.1,Otro modelo (falsificación)
|
||||
gg.print.2,"Reimpreso, torcido (falsificación)"
|
||||
gg.point.h,Señalar
|
||||
gg.ex.card,"Ejemplo: {0}, salud {1}%"
|
||||
gg.ex.base,Valor base: +{0}
|
||||
gg.ex.fan,Aspa mellada: -{0}
|
||||
gg.ex.fin,Contactos opacos: -{0}
|
||||
gg.ex.seal,Sello ausente: -{0}
|
||||
gg.ex.total,Valor final: {0}
|
||||
gg.ex.note,Cada descuento es una parte del valor base; se suman y se deducen.
|
||||
gg.ex.fan1,Aspas con polvo: -{0}
|
||||
gg.ex.fin2,Contactos oxidados: -{0}
|
||||
gg.ex.brk,Soporte rayado: -{0}
|
||||
gg.ex.nodisc,Sin descuentos: -0
|
||||
gg.ex.fake,"Indicado {0}, chip real {1}: se valora el chip real"
|
||||
gg.ex.claimed,Precio del modelo indicado: {0}
|
||||
gg.ex.gap,Diferencia con la oferta: {0}
|
||||
gg.ex.h2,Ejemplo de tasación: falsificación
|
||||
gg.ex.h3,Ejemplo de tasación: muy desgastada
|
||||
gg.ex.h4,Ejemplo de tasación: poco uso
|
||||
gg.ex.h5,Ejemplo de tasación: nueva
|
||||
lbl.price,Precio de etiqueta: {0}
|
||||
lbl.row.count,Ventiladores
|
||||
lbl.row.pin,Alimentación
|
||||
lbl.count.1,1 ventilador
|
||||
lbl.count.2,2 ventiladores
|
||||
lbl.count.3,3 ventiladores
|
||||
lbl.pin.0,6 pines
|
||||
lbl.pin.1,8 pines
|
||||
lbl.pin.2,2 × 8 pines
|
||||
gg.p1.body,"Las tarjetas gráficas son el componente central de toda plataforma de minería y la mercancía más falsificada en el mercado de segunda mano.\nCuatro puntos indican si una tarjeta es auténtica: número de ventiladores, conector de alimentación, serigrafía trasera y número de serie. Solo es auténtica la tarjeta que coincide con su modelo declarado en los cuatro; una sola discrepancia supone una falsificación.\nEl valor de una tarjeta depende del modelo del chip real y de su estado, y cada señal de desgaste reduce el precio.\n\nEsta guía reúne todos los conocimientos necesarios para tasar una tarjeta gráfica."
|
||||
gg.p2.h,Modelos de tarjeta
|
||||
gg.p2.body,El modelo determina el número de ventiladores y el conector de alimentación. Una falsificación es un chip de modelo inferior dentro de la carcasa de un modelo superior; su rendimiento y su valor son los del chip real.
|
||||
gg.tier.0,"RTX 60 / RX 70: 6 pines, 1 vent."
|
||||
gg.tier.1,"RTX 70 / RX 80: 8 pines, 2 vent."
|
||||
gg.tier.2,"RTX 80 / RX 800: 8 pines, 3 vent."
|
||||
gg.tier.3,"RTX 90 / RX 900: 2×8 pines, 3 vent."
|
||||
gg.count.h,Número de ventiladores
|
||||
gg.count.body,"El modelo determina el número de ventiladores: uno en las RTX 60 y RX 70, dos en las RTX 70 y RX 80, tres en las RTX 80, RTX 90, RX 800 y RX 900.\nUn número de ventiladores que no coincide con el modelo declarado indica una falsificación."
|
||||
gg.pin.h,Conector de alimentación
|
||||
gg.pin.body,"El conector de alimentación también lo determina el modelo: 6 pines en las RTX 60 y RX 70, 8 pines en las RTX 70, RTX 80, RX 80 y RX 800, 2 × 8 pines en las RTX 90 y RX 900.\nUn conector de alimentación que no coincide con el modelo declarado indica una falsificación."
|
||||
gg.serial.body,"El número de serie va en una pegatina en el reverso, con este formato: prefijo, código de modelo, guion, código de fábrica de dos dígitos, guion y número correlativo de cuatro dígitos, por ejemplo PB2-21-6251."
|
||||
gg.serial.rule,"Los códigos de modelo 1 a 4 corresponden a RTX 60 / RX 70, RTX 70 / RX 80, RTX 80 / RX 800 y RTX 90 / RX 900.\nUn código de modelo que no coincide con el modelo (la pegatina es del chip original), o un código de fábrica o una longitud inválidos (pegatina añadida después), indica una falsificación. El código de fábrica solo sirve para comprobar la autenticidad y no afecta al precio."
|
||||
gg.print.note,"Una tarjeta solo es auténtica si el número de ventiladores, el conector de alimentación, la serigrafía y el número de serie coinciden todos con el modelo. Una falsificación falla al menos en uno, pero puede imitar bien los demás; por eso hay que comprobar cada punto."
|
||||
gg.point.body,"Se inspecciona con la lupa. En la barra de etiquetas, solo la fila del modelo tiene el botón «Señalar modelo»; las cuatro filas de debajo (ventiladores, alimentación, serigrafía trasera, serie) son de solo lectura, y cada una de las cuatro filas de condición —aspas, contactos, soporte, sello— tiene su propio «Señalar».\nAl señalar un problema de condición oculto, esa fila pasa al estado real y el precio baja la diferencia; al señalar algo cierto, la otra parte lo rechaza y la reputación se resiente.\nSi los ventiladores, la alimentación, la serigrafía trasera o el número de serie no coinciden con el modelo indicado, señala el modelo: la tarjeta queda declarada falsificación, el modelo vuelve al chip real y el precio se recalcula para ese chip.\n\nLas tarjetas que traen los clientes del gremio de tasadores funcionan igual: al señalar los problemas cambia la estimación, hasta que se indica el valor correcto."
|
||||
gg.ex.serial,Número de serie: {0}
|
||||
gg.ex.h,"Ejemplo de tasación: aspa mellada, contactos opacos, sello ausente"
|
||||
rig.label.status,Estado
|
||||
rig.st.cards,Tarjetas
|
||||
rig.st.power,Consumo
|
||||
rig.st.hash,Tasa de hash
|
||||
rig.st.kj,{0} kJ/día
|
||||
lbl.point.model,Señalar modelo
|
||||
col.crcprice,Precio en CRC
|
||||
swap.pay,Pagar
|
||||
swap.get,Recibir
|
||||
swap.preview,"Aprox. {0} {1} {2} fondo(s), pérdida {3} %"
|
||||
swap.go,Canjear
|
||||
swap.same,Las monedas a pagar y recibir deben ser distintas.
|
||||
mint.need,Requiere {0} CRC y {1} SPARK
|
||||
mint.reserve,Cobertura {0} % Colateral {1} %
|
||||
mint.queue,Órdenes pendientes
|
||||
mint.order,"{0} {1} CRA, día {2}"
|
||||
stake.coin,Moneda a depositar
|
||||
stake.sum.via,Canjear {0} {1} → aprox. {2} CRA y poner en staking
|
||||
nightlog.cra.lost,El emisor no respondió: la orden ({1}) de {0} CRA se perdió.
|
||||
news.crawarn.desc,Alguien está contando la reserva de la Revolución y quizá los CRA en staking no se puedan redimir por completo. Desbloquear tarda cuatro días; algunos dicen que es hora de actuar.
|
||||
news.cralow.desc,La cobertura de la reserva se agota y la Revolución ha recortado la tasa de staking de CRA a una fracción.
|
||||
poin.sub.funds,Fondos
|
||||
funds.receive,Depósito
|
||||
funds.send,Retiro
|
||||
funds.bank,Cuenta bancaria
|
||||
funds.wallet,Billetera
|
||||
funds.to,Dirección de destino
|
||||
funds.go,Enviar
|
||||
funds.sending,Enviando {0} {1} a {2}
|
||||
funds.confirm,Confirmación {0}/{1}
|
||||
funds.done,{0} {1} llegaron a {2}.
|
||||
funds.done.void,{0} {1} enviados; la dirección no tiene dueño y las monedas se perdieron.
|
||||
funds.err.addr,Dirección no válida.
|
||||
funds.err.self,Esa es la dirección de depósito de Poinbase.
|
||||
funds.err.known,Esa dirección solo acepta pagos contra una factura.
|
||||
funds.err.fee,La cantidad no cubre la comisión de gas.
|
||||
wallets.sub.explorer,Explorador
|
||||
explorer.search,Dirección
|
||||
explorer.all,Recientes
|
||||
explorer.none,Sin transferencias.
|
||||
explorer.col.block,Bloque
|
||||
explorer.col.amount,Cantidad
|
||||
explorer.mixer,Mezclador
|
||||
cra.mint,Acuñar
|
||||
cra.burn,Quemar
|
||||
mint.h,Acuñación oficial (CRC + SPARK)
|
||||
mint.sum.in,Acuñar {0} CRA con {1} CRC y {2} SPARK ({3}–{4} días)
|
||||
mint.sum.out,Quemar {0} CRA por CRC y SPARK ({1} días)
|
||||
mint.done.in,Orden de acuñación enviada; vence el día {0}.
|
||||
mint.done.out,Orden de quema enviada; vence el día {0}.
|
||||
nightlog.cra.minted,{0} CRA acuñados, ya en staking ({1}).
|
||||
nightlog.cra.burned,"{0} CRA quemados: +{1} CRC, +{2} SPARK ({3})."
|
||||
predict.clue.subsidy,"Reserva al {0}%; a cero, la advertencia es segura"
|
||||
air.noapprove,sin permiso sobre tokens
|
||||
tab.gray,Red gris
|
||||
wallets.sub.list,Lista
|
||||
entry.web3.l1,Comercio descentralizado y rendimiento
|
||||
entry.mining.l1,Estado de los equipos y ganancias nocturnas
|
||||
entry.gray.l1,Mezclador y tienda
|
||||
entry.wallets.l1,Billeteras de hardware y explorador
|
||||
entry.wallets.l2,Billeteras {0} / {1}
|
||||
black.sell.add,Añadir artículos
|
||||
black.sell.back,Volver al escaparate
|
||||
black.sell.kinds,En venta {0}/{1} tipos
|
||||
black.sell.have,{0} en venta
|
||||
black.sell.coins,Monedas aceptadas
|
||||
black.sell.off,Retirar
|
||||
black.sell.off.n,Retirar ×{0}
|
||||
black.sell.nocoin,Acepta al menos una moneda.
|
||||
black.sell.empty,Nada en venta.
|
||||
black.sell.delisted,{0} retirado(s); la mercancía vuelve al almacén.
|
||||
black.sell.partial,"{0} puestos en venta, {1} no se pudieron poner."
|
||||
black.sell.limit.stack,Máximo {0} unidades por artículo.
|
||||
black.sell.limit.kinds,Máximo {0} tipos a la vez.
|
||||
shelf.fab,Estante {0}
|
||||
delist.fab,Confirmar retirada {0}
|
||||
black.fee.h,Listo para publicar
|
||||
black.fee.line,{0} ×{1} · precio {2} ({3})
|
||||
black.fee.total,Tarifa de publicación {0}
|
||||
black.fee.sum,Tarifa de publicación ({0} art.)
|
||||
black.sale.Sold,"vendido, pago el día {0} en {1}"
|
||||
explorer.col.day,Día
|
||||
explorer.day,Día {0}
|
||||
explorer.pool,pool de RatDigg
|
||||
explorer.desk,mesa Ponero
|
||||
black.fee.pay,Pagar la tarifa de publicación
|
||||
explorer.col.from,De
|
||||
explorer.col.to,A
|
||||
rig.st.cond,Condición
|
||||
asic.st.dead,Quemado
|
||||
perp.preview,Valor nocional {0} precio medio est. {1} (deslizamiento {2}%)
|
||||
perp.sim.close,Cierre valor nocional {0} precio medio est. {1} (deslizamiento {2}%)
|
||||
perp.sim.close2,Comisión {0} se recuperan unos {1} CRC (G/P {2})
|
||||
trade.sim.sell,La venta da unos {0} {1} medio {2} deslizamiento {3}%
|
||||
trade.sim.buy,La compra cuesta unos {0} {1} medio {2} deslizamiento {3}%
|
||||
trade.amount.unit,Cantidad ({0})
|
||||
trade.fee,Comisión {0}%
|
||||
trade.sim.thin,Supera la liquidez del pool
|
||||
news.wipe.down.title,{0} cae un {1}% en un día: {2} traders liquidados
|
||||
news.wipe.down.desc,"En el último día se liquidaron {1} posiciones largas en perpetuos de {0}, por un total de {2} créditos. El fondo de seguro de Poinbase queda en {3} créditos."
|
||||
news.wipe.up.title,{0} sube un {1}% en un día: {2} traders liquidados
|
||||
news.wipe.up.desc,"En el último día se liquidaron {1} posiciones cortas en perpetuos de {0}, por un total de {2} créditos. El fondo de seguro de Poinbase queda en {3} créditos."
|
||||
hot.name,Vendedor
|
||||
hot.intro.CRT,"Las cosas están tensas y este CRT quema. Necesito efectivo, rápido."
|
||||
hot.intro.PSC,"La billetera de una granja de minería cambió de dueño anoche. El PSC lo tengo yo, y solo acepto efectivo."
|
||||
hot.intro.PONERO,"Un rescate, en Ponero. Nadie puede rastrearlo. Solo efectivo."
|
||||
hot.offer,"{0} {1}, que valen {2} al precio de hoy. Dame {3} en efectivo y las monedas son tuyas ahora mismo."
|
||||
hot.choice.yes,Aceptar
|
||||
hot.choice.no,Rechazar
|
||||
hot.say.yes,Trato hecho.
|
||||
hot.say.no,No pienso tocar eso.
|
||||
hot.done,Monedas enviadas. Nunca nos vimos.
|
||||
hot.refused,Ya habrá otro que lo quiera.
|
||||
hot.nocash,¿Ni siquiera tienes el efectivo? Olvídalo.
|
||||
hot.nowallet,"No hay billetera conectada, ¿adónde mando las monedas? Olvídalo."
|
||||
hot.sting,Quieto. Seguridad. Compra de fondos robados: el efectivo queda confiscado y esto va a tu expediente.
|
||||
hw.err.poinbase,Poinbase no acepta {0}.
|
||||
@@ -0,0 +1,980 @@
|
||||
# Probably Decentralized localization table: French (fr)
|
||||
# AI translation, not proofread. Source: en.csv. Format: key,text (text may be quoted; \n is a line break).
|
||||
upgrade.tab,Web3
|
||||
upgrade.title,Communauté de gouvernance Web3
|
||||
upgrade.desc,"Les membres reçoivent un terminal de trading, un portefeuille matériel, une plateforme de minage, une carte graphique RTX 60 et un guide d'expertise de cartes graphiques. Le terminal intègre la banque, la bourse Poinbase ainsi que les pages Web3, Minage et Portefeuilles. D'autres cartes et plateformes sont vendues par le Pr Jackson."
|
||||
item.terminal.name,Terminal de trading
|
||||
item.terminal.desc,"Portefeuille, bourse Poinbase et rapport de minage nocturne."
|
||||
item.rig.name,Plateforme de minage
|
||||
item.rig.desc,Jusqu'à {0} cartes graphiques. Taux de hachage : {1} MH/s. Consommation : {2} kJ/j.
|
||||
rig.label.modules,Modules
|
||||
item.rig.modules,"Modules : taux de hachage {0}, consommation {1}, usure {2}."
|
||||
item.rig.next,Emplacement {0} : faire glisser {1} sur la plateforme de minage ({2}/{3}).
|
||||
mat.common_electronic,Composants électroniques courants
|
||||
mat.rare_electronic,Composants électroniques rares
|
||||
rig.label.cards,Cartes graphiques
|
||||
item.gpu.name,{0} {1}
|
||||
item.gpu.desc,Taux de hachage nominal {0} MH/s. Consommation nominale {1} kJ/j. État : {2}.
|
||||
item.gpu.burnt.name,{0} {1} grillée
|
||||
item.gpu.burnt.desc,Cette carte ne fonctionne plus.
|
||||
term.title,Terminal de trading
|
||||
tab.report,Rapport
|
||||
wallet.line,{0} : {1} (environ {2} crédits)
|
||||
wallet.empty,Le portefeuille est vide.
|
||||
wallet.total,Valeur totale : {0} crédits
|
||||
wallet.taint,Valeur contaminée : {0} crédits
|
||||
trade.amount,Montant
|
||||
trade.deposit,Déposer des crédits en CRC
|
||||
trade.withdraw,Retirer des CRC en crédits
|
||||
trade.pair,{0}/{1} ({2})
|
||||
trade.price,Prix {0}
|
||||
trade.buy,Acheter
|
||||
trade.sell,Vendre
|
||||
venue.Exchange,Poinbase
|
||||
venue.Dex,DEX
|
||||
venue.Darknet,Darknet
|
||||
msg.amount,Entrez un montant.
|
||||
msg.balance,Solde insuffisant.
|
||||
msg.trade,"Payé {0} {1}, reçu {2} {3}."
|
||||
msg.deposit,{0} crédits déposés en CRC.
|
||||
msg.cashout,{0} crédits reçus. Taxe : {1} crédits.
|
||||
msg.aml_light,Contrôle de conformité : {0} crédits de fonds contaminés ont été retenus.
|
||||
msg.aml_heavy,Contrôle de conformité : {0} crédits de fonds contaminés ont été saisis et signalés à la Sécurité.
|
||||
report.none,Aucun rapport de minage pour le moment.
|
||||
report.day,Nuit du jour {0}
|
||||
report.rigs,Plateformes alimentées : {0} sur {1}
|
||||
report.hash,Taux de hachage : {0} MH/s (réseau {1} MH/s)
|
||||
report.mined,Miné : {0} PSC (environ {1} crédits)
|
||||
report.energy,Énergie consommée : {0} kJ
|
||||
report.burnt,Cartes grillées : {0}
|
||||
report.price,Prix du PSC : {0} crédits
|
||||
nightlog.mined,Les plateformes de minage ont produit {0} PSC.
|
||||
nightlog.burnt,Une {0} a grillé.
|
||||
coinpay.line,Marché conclu. {0} {1}.
|
||||
nightlog.coinpay,Les paiements en pièces ont réglé {0} crédits ; les pièces ont été transférées sur le portefeuille chaud.
|
||||
nightlog.unpowered,Plateformes de minage ou mineurs non alimentés : {0}.
|
||||
news.open.title,Poinbase liste le PSC
|
||||
news.open.desc,La bourse Poinbase du Niveau supérieur liste désormais le PSC contre le CRC. Les cartes graphiques sont très demandées dans toute la station.
|
||||
news.halving.title,Récompense de bloc du PSC divisée par deux
|
||||
news.halving.desc,Les mineurs reçoivent désormais moitié moins de pièces par nuit.
|
||||
appraisal.gpu,Carte graphique
|
||||
dealer.name,Dealeur de matériel d'occasion
|
||||
dealer.line1.1,Cartes de déstockage d'une ferme de minage. L'état est noté à côté du nom.
|
||||
dealer.line1.2,"Quelques cartes qui ont miné, pas cher."
|
||||
dealer.line1.3,Récupérées en chemin. Prix direct.
|
||||
dealer.line2.1,"Regarde par toi-même, retourne-les pour vérifier le dos."
|
||||
dealer.line2.2,Pas de garantie. Vérifie bien avant de prendre.
|
||||
dealer.line2.3,"Si ça t'intéresse, le prix est négociable."
|
||||
inspect.flip.back,Retourner
|
||||
inspect.flip.front,Face avant
|
||||
item.gpu.grade.1,comme neuf
|
||||
item.gpu.grade.2,correct
|
||||
item.gpu.grade.3,nettement usé
|
||||
item.gpu.grade.4,très usé
|
||||
point.none.1,Elle n'a aucun problème. Tu as dû mal voir.
|
||||
point.none.2,Où ça ? N'invente rien si tu n'achètes pas.
|
||||
point.worn.1,"... Bon, d'accord, elle a ce défaut. Je te fais un rabais."
|
||||
point.worn.2,"Tu as l'œil. D'accord, va pour ce prix."
|
||||
point.fake.1,... Tu m'as eu. Elle a été reflashée. Je te la fais à sa vraie valeur.
|
||||
point.fake.2,"Tss, c'est pas la puce d'origine. Bon, au prix de la vraie puce, alors."
|
||||
lbl.fan.0,Pales propres
|
||||
lbl.fan.1,Pales poussiéreuses
|
||||
lbl.fan.2,Pale ébréchée
|
||||
lbl.fingers.0,Brillants
|
||||
lbl.fingers.1,Ternes
|
||||
lbl.fingers.2,Oxydés
|
||||
lbl.print.0,Conforme au modèle
|
||||
lbl.print.1,Autre modèle imprimé
|
||||
lbl.print.2,"Réimprimé, de travers"
|
||||
lbl.said," (selon le vendeur : {0})"
|
||||
lbl.point,Signaler
|
||||
lbl.edit,Modifier
|
||||
cust.fake.1,Ce n'est pas ce qu'indique l'étiquette. Tu essaies de me refourguer un faux ?
|
||||
cust.fake.2,Le modèle ne correspond pas. Ce n'est pas la puce annoncée.
|
||||
cust.worn.1,Ce n'est pas ce que tu as écrit. Tu n'as pas mentionné les défauts.
|
||||
cust.worn.2,L'état sur l'étiquette est faux. Pas à ce prix-là.
|
||||
lbl.row.fan,Pales
|
||||
lbl.row.fingers,Contacts
|
||||
lbl.row.bracket,Équerre
|
||||
lbl.row.print,Sérigraphie dos
|
||||
lbl.row.serial,N° de série
|
||||
lbl.row.seal,Scellé
|
||||
lbl.bracket.0,Intacte
|
||||
lbl.bracket.1,Rayée
|
||||
lbl.serial.0,Valide
|
||||
lbl.serial.1,Code usine ou longueur incorrects
|
||||
lbl.serial.2,Code de modèle non correspondant
|
||||
lbl.seal.0,Intact
|
||||
lbl.seal.2,Manquant
|
||||
item.guide.name,Guide d'expertise de cartes graphiques
|
||||
item.guide.desc,Un guide pour reconnaître les contrefaçons de cartes graphiques et en déterminer la valeur.
|
||||
lbl.row.spec,Modèle
|
||||
news.prehalving.title,Halving du PSC imminent
|
||||
news.prehalving.desc,"Dans trois jours, les mineurs recevront moitié moins de jetons par nuit. Les détenteurs s'attendent à une hausse du cours."
|
||||
tab.home,Accueil
|
||||
tab.bank,Banque
|
||||
tab.poinbase,Poinbase
|
||||
tab.web3,Web3
|
||||
home.enter,Entrer
|
||||
home.open,Ouvrir
|
||||
home.summary,Crédits {0} | Actifs on-chain environ {1} crédits
|
||||
home.lastnight,"Nuit du jour {0} : {1} PSC minés, {2} / {3} plateformes alimentées"
|
||||
entry.bank,Banque
|
||||
entry.bank.l1,"Dépôts, retraits, loyer"
|
||||
entry.bank.l2,Crédits {0}
|
||||
entry.poinbase,Poinbase
|
||||
entry.poinbase.l1,Bourse conforme
|
||||
entry.poinbase.l2,PSC {0} crédits
|
||||
entry.web3,Web3
|
||||
entry.web3.l2,Environ {0} crédits
|
||||
entry.help,Aide
|
||||
entry.help.l1,Manuel Web3
|
||||
bank.cash,Crédits : {0}
|
||||
bank.rent,"Loyer : {0} crédits, échéance dans {1} jour(s)"
|
||||
bank.crc,Compte Poinbase (CRC) : {0}
|
||||
poin.account,"Compte Poinbase : CRC {0}, PSC {1}"
|
||||
avg.line,Prix d'achat moyen de {0} : {1} crédits
|
||||
avg.short,achat moy. {0}
|
||||
avg.none,—
|
||||
col.asset,Actif
|
||||
col.amount,Montant
|
||||
col.value,Valeur
|
||||
col.avg,Achat moy.
|
||||
bank.cash.k,Crédits
|
||||
bank.rent.k,Loyer
|
||||
bank.rent.v,"{0}, échéance dans {1} jour(s)"
|
||||
bank.crc.k,Compte Poinbase (CRC)
|
||||
poin.account.h,Compte Poinbase
|
||||
trade.h,Trading
|
||||
web3.wallet.h,Portefeuille on-chain
|
||||
stable.ok,Arrimé
|
||||
stable.depeg,Désarrimé
|
||||
stable.warn,Attention : couverture de réserve du staking au plus bas
|
||||
stable.spiral,Effondrement en cours
|
||||
aml.taint,Part de contamination du compte : {0} %
|
||||
mixer.h,Mixeur
|
||||
mixer.ok,Statut : fonctionnement normal
|
||||
mixer.sanctioned,Statut : sanctionné (encore {0} jour(s)). Les pièces retirées pendant cette période sont signalées.
|
||||
mixer.pending,Dépôts en attente
|
||||
mixer.none,Aucun dépôt en attente.
|
||||
mixer.col.taint,Contamination
|
||||
mixer.col.ready,Échéance
|
||||
mixer.day,Jour {0}
|
||||
mixer.deposit,Dépôt
|
||||
mixer.balance,Solde : {1} {0}
|
||||
mixer.rounds,Tours
|
||||
mixer.preview,"Retour estimé : {0} {1}, contamination réduite d'environ {2} %, disponible au jour {3}."
|
||||
mixer.go,Déposer au mixeur
|
||||
mixer.min,Les dépôts doivent valoir au moins {0} crédits.
|
||||
mixer.done,{0} {1} déposés ; retour au jour {2}.
|
||||
mixer.upgrade.title,Mixeur
|
||||
mixer.upgrade.desc,"Débloque le mixeur sur la page Réseau gris du terminal : déposez des pièces contaminées pour les récupérer quelques jours plus tard avec une contamination réduite. Les retraits de pièces fraîchement mixées font l'objet d'un contrôle plus strict ; en période de répression, le mixeur peut être sanctionné et les pièces retirées pendant cette période sont signalées."
|
||||
news.sanction.title,Mixeur placé sur la liste des sanctions
|
||||
news.sanction.desc,La Sécurité a sanctionné plusieurs services de mixage. Les fonds retirés des mixeurs au cours des prochains jours seront considérés comme suspects.
|
||||
nightlog.mixer,Le mixeur a restitué {0} {1} ; contamination {2} -> {3}.
|
||||
nightlog.mixer_flag," (retiré pendant les sanctions ; adresse signalée)"
|
||||
nightlog.mixer_rug,L'opérateur du mixeur a pris la fuite : {0} {1} ne sont jamais revenus.
|
||||
web3.sub.trade,Trading
|
||||
gray.sub.mixer,Mixeur
|
||||
msg.frozen,Ces pièces sont gelées jusqu'à leur dégel.
|
||||
wallet.frozen,"{0} : {1} gelés, dégel au jour {2}"
|
||||
nightlog.crt_freeze,Le Marché noir a transmis des adresses pendant la répression : {0} de vos CRT sont gelés jusqu'au jour {1}.
|
||||
nightlog.thaw,Les {0} {1} gelés ont été dégelés.
|
||||
news.crtfreeze.title,Le Marché noir gèle des adresses CRT face à la répression
|
||||
news.crtfreeze.desc,"D'après les rumeurs, le Marché noir a fourni une liste d'adresses CRT à la Sécurité en échange de sa tranquillité. Les détenteurs à faible réputation ont plus de risques d'être gelés."
|
||||
black.upgrade.title,Boutique Web3
|
||||
black.upgrade.desc,"Débloque la boutique sur la page Réseau gris du terminal : la branche on-chain de la faction du Marché noir. Réapprovisionnement hebdomadaire en contrebande, parfois en objets high-tech et cartes graphiques (à prix majoré) ; achetez au comptant ou commandez et attendez un livreur. Cryptos uniquement (PSC, CRT, CRA, Ponero), pièces contaminées acceptées. Requiert de la réputation au Marché noir ; hors ligne pendant les répressions."
|
||||
black.offline,L'accès on-chain de la boutique est hors ligne pendant la répression.
|
||||
black.closed,Une réputation de {0} au Marché noir est requise pour entrer dans la boutique (actuellement {1}).
|
||||
black.sub.buy,Achats
|
||||
black.shop.h,Comptoir spot
|
||||
black.rep,Réputation au Marché noir : {0}
|
||||
black.empty,Épuisé pour cette semaine.
|
||||
black.offer,{0} x{1} {2} crédits
|
||||
black.buy,Acheter
|
||||
black.bought,Transaction conclue : {0} est dans la réserve.
|
||||
black.pay.h,Paiement
|
||||
black.desk.h,Comptoir Ponero
|
||||
black.desk.left,Restant aujourd'hui : {0} (limite {1})
|
||||
black.desk.price,Prix du Ponero : {0}
|
||||
black.desk.swap,Échange
|
||||
black.desk.in,Vers Ponero
|
||||
black.desk.out,Depuis Ponero
|
||||
black.desk.go,Échanger
|
||||
black.desk.fail,"Échec de l'échange : solde, limite ou montant incorrect."
|
||||
black.sub.orders,Commandes
|
||||
black.rugged,La plateforme est fermée ; personne ne rouvrira avant {0} jour(s).
|
||||
black.seller,"Transactions : {1}, {2} % d'avis positifs"
|
||||
black.orders.h,Catalogue des commandes
|
||||
black.order,Commander
|
||||
black.mode.Escrow,Tiers de confiance
|
||||
black.mode.Advance,Déblocage anticipé
|
||||
black.ordered,"Commandé : {0}, livraison au jour {1}."
|
||||
black.mine.h,Mes commandes
|
||||
black.mine.none,Aucune commande pour le moment.
|
||||
black.mine.line,"{0} ({1}, {2}) : {3}, jour {4}"
|
||||
black.state.Pending,en transit
|
||||
black.state.Ready,arrivé
|
||||
black.state.Done,récupéré
|
||||
black.state.Refunded.scam,"vendeur enfui, remboursé"
|
||||
black.state.Lost.scam,"vendeur enfui, fonds perdus"
|
||||
black.state.Lost.rug,"rug pull de la plateforme, fonds perdus"
|
||||
black.state.Lost.intercept,intercepté
|
||||
black.forum.h,Infos secrètes du forum
|
||||
black.forum.quiet,Calme ces derniers temps.
|
||||
black.forum.scam,Quelqu'un affirme que {0} empoche l'argent et ne livre jamais.
|
||||
black.forum.rug,"Les retraits sont lents ces derniers temps, le site propose des promos et de nombreux fils de plainte ont été supprimés."
|
||||
nightlog.bm.scam_refund,Marché noir : le vendeur {0} a fui ; les fonds sous tiers de confiance pour {1} ont été remboursés.
|
||||
nightlog.bm.scam_loss,Marché noir : le vendeur {0} a encaissé les fonds du déblocage anticipé et a fui ; {1} est perdu ({2} crédits).
|
||||
nightlog.bm.intercept,Marché noir : le colis contenant {0} a été intercepté ; le paiement de {1} crédits est perdu.
|
||||
nightlog.bm.rug,Marché noir : la plateforme a fait un rug pull ; les fonds en transit pour {0} ({1}) sont perdus.
|
||||
nightlog.bm.reopen,Marché noir : quelqu'un a rouvert à l'ancien endroit.
|
||||
news.bmrug.title,Rug pull de la plateforme du Marché noir
|
||||
news.bmrug.desc,"L'accès on-chain du Marché noir a disparu du jour au lendemain, anéantissant tous les fonds sous tiers de confiance et en déblocage anticipé. Un nouvel accès apparaîtra dans quelques jours."
|
||||
courier.name,Livreur
|
||||
courier.line1.1,La livraison est là.
|
||||
courier.line1.2,Un colis pour vous.
|
||||
courier.line2.1,Ne me dites pas ce qu'il y a dedans. Je ne veux pas savoir.
|
||||
courier.line2.2,Je pose ça là. Je file.
|
||||
gray.sub.black,Boutique
|
||||
black.stock,Restant : {0}
|
||||
black.price,{0} crédits
|
||||
black.noadvance,Pas de déblocage anticipé
|
||||
black.kind.gpu,GPU état {0} %
|
||||
black.kind.Contraband.1,Contrebande (faible)
|
||||
black.kind.Contraband.2,Contrebande (moyenne)
|
||||
black.kind.Contraband.3,Contrebande (élevée)
|
||||
black.kind.Tech,High-tech (majoration)
|
||||
nightlog.bm.ready,Marché noir : {0} est arrivé ; un livreur passera dès l'ouverture.
|
||||
guide.web3.title,Manuel Web3
|
||||
guide.web3.text,"Banque et trading : la page Banque est en lecture seule et affiche les espèces, le loyer et les CRC du compte Poinbase. La page Fonds de Poinbase gère dépôts et retraits ; on choisit d'abord la pièce : le CRC passe par le compte bancaire ou le portefeuille, les autres pièces uniquement par le portefeuille. Le dépôt depuis la banque convertit les crédits en CRC sur votre compte Poinbase ; le retrait vers la banque reconvertit les CRC en crédits et passe par un contrôle de conformité, qui évalue la contamination du compte Poinbase. Un retrait vers un portefeuille demande l'adresse du destinataire et plusieurs confirmations avant d'arriver ; les frais de gas sont fixés au niveau normal et prélevés sur la pièce envoyée. Un format d'adresse ou un chiffre de contrôle incorrect est refusé ; une adresse au format valide mais que personne n'utilise fait perdre les pièces envoyées.¶Trading : PSC signifie Probably Stolen Coin, la pièce minée par les cartes graphiques et les mineurs (machines). Le spot de Poinbase propose deux paires, PSC/CRC et SPARK/CRC, selon la pièce choisie sur le graphique. Les achats comme les ventes se saisissent en quantité de la monnaie échangée ; l'aperçu indique la monnaie de cotation payée ou reçue, le prix moyen inclut les frais et le glissement non.¶La page de trading Web3 permet d'échanger deux pièces au choix, toujours via le CRC : si le CRC est d'un côté, un seul pool est utilisé, sinon deux pools, avec deux frais et un glissement cumulé ; l'aperçu indique le montant obtenu, le nombre de pools traversés et la perte. Les échanges entre stablecoins (CRT ou CRA contre CRC) passent par des pools stables : {StableFee:%} de frais et quasiment aucun glissement près de l'ancrage ; en cas de désancrage la liquidité s'amincit, et en cas d'effondrement elle est retirée et le glissement s'envole.§Portefeuilles matériels : les pièces sur la blockchain sont conservées dans des portefeuilles matériels PLEDGER, chacun avec ses propres soldes et sa contamination. Un portefeuille est un objet : glissez-le sur le terminal de trading pour le charger. Ouvrez-le sur la page Portefeuilles du terminal ; connectez et déconnectez-le en haut à droite du terminal. Le trading de la page Web3, la boutique et le mixeur de la page Réseau gris utilisent le portefeuille connecté ; sans portefeuille ou sans connexion, ils sont en lecture seule et tous les soldes affichent 0. Les clients qui paient en pièces paient sur le portefeuille connecté.¶Les paiements (boutique, mixeur, comptoir Ponero, frais de mise en vente) débutent par une facture sur le terminal ; saisissez l'adresse du destinataire sur le portefeuille et maintenez ✓ pour signer. Les deux derniers caractères d'une adresse sont une somme de contrôle, de sorte qu'une faute de frappe d'un caractère est généralement interceptée ; il arrive parfois qu'elle soit valide par hasard et les pièces partent alors vers une adresse inutilisée. Les échanges sur le DEX nécessitent également une signature sur le portefeuille.¶Poinbase est un compte dépositaire ; le dépôt s'effectue depuis le portefeuille vers l'adresse de dépôt de Poinbase (uniquement PSC, CRC et SPARK ; la plateforme réglementée n'accepte ni le CRT du Marché noir ni le CRA de la Révolution, et le portefeuille bloque leur envoi vers l'adresse de dépôt), le retrait se lance depuis la page Fonds de Poinbase. L'Explorateur de la page Portefeuilles permet de consulter les transferts par adresse, en n'affichant que les transferts réellement effectués : chaque entrée et sortie de vos portefeuilles (transferts, échanges DEX et autres appels de contrat, gains des mineurs, retraits, pièces que d'autres vous envoient) ; Ponero est une monnaie de confidentialité et n'apparaît jamais. D'autres portefeuilles matériels sont vendus par le Pr Jackson ; glissez-en un sur le terminal de trading pour l'ajouter, jusqu'à {WalletMax} au total. La boutique en propose des moins chers. Un portefeuille devenu inutile peut être détruit sur la page Portefeuilles ; ses pièces sont perdues définitivement, et tout ce qui est envoyé ensuite à son adresse l'est aussi.¶Les transferts sont soumis à des frais de gas : lent, normal ou rapide, et le prix du gas monte et descend sur environ une semaine ; lorsque le réseau est saturé, les frais de gas augmentent et les transactions lentes peuvent être évincées de la mempool. Vérifiez l'adresse complète avant d'envoyer.§Staking : le CRA staké dans le pool de la Révolution rapporte un taux quotidien capitalisé dans le montant staké ; retirer nécessite d'en faire la demande préalable et d'attendre quatre jours, sans intérêt durant cette période ni moyen de récupérer les fonds plus tôt. Le CRA est partiellement collatéralisé : chaque CRA est soutenu par la réserve de CRC détenue par la Révolution et par le jeton d'équilibre SPARK ; le taux de couverture de laLine truncated
|
||||
courier.odd1,...Le colis est là.
|
||||
courier.odd2,(Sa main reste dans sa poche.) Signez ici.
|
||||
courier.sign,Signer
|
||||
courier.refuse,Refuser
|
||||
courier.signed,"Bien. Ne bougez plus, Sécurité."
|
||||
courier.refused,"...Bon, laissez tomber."
|
||||
black.state.Lost.seized,saisi
|
||||
black.state.Lost.refused,refusé
|
||||
black.forum.easy,"Trop fluide ces derniers temps : les vendeurs expédient plus vite que jamais, et il y a de nouveaux comptes jamais vus."
|
||||
black.forum.busted,"Il paraît que {0} a été arrêté, et l'historique des commandes traîne toujours."
|
||||
nightlog.bm.trap.honeypot,"Marché noir : la plateforme a été reprise par les forces de l'ordre ; votre {0} a été tracé, infraction enregistrée : {1}."
|
||||
nightlog.bm.trap.seller,"Marché noir : un vendeur a été arrêté et l'historique des commandes vous implique : {0}, infraction enregistrée : {1}."
|
||||
tab.mining,Minage
|
||||
courier.sign.say,Je signe.
|
||||
courier.refuse.say,Pas question. Renvoyez-le.
|
||||
black.forum.busted_buyer,"Il paraît qu'une vague d'acheteurs a été arrêtée, et les registres de vente sont encore sur la plateforme."
|
||||
nightlog.bm.sale_sold,Marché noir : votre {0} s'est vendu pour {1} ; paiement au jour {2}.
|
||||
nightlog.bm.sale_paid,"Marché noir : le paiement de {1} pour {0} est arrivé (CRT), dont contamination {2}."
|
||||
nightlog.bm.sale_fake,Marché noir : l'acheteur a vu que {0} était une contrefaçon et l'a renvoyé ; votre évaluation a baissé.
|
||||
nightlog.bm.sale_rug,Marché noir : la plateforme a fait un rug pull ; votre {0} et le paiement ({1}) ont disparu.
|
||||
black.sub.sell,Vente
|
||||
black.sell.h,Vente
|
||||
black.sell.mult,Multiplicateur de prix
|
||||
black.sell.none,Rien de vendable en stockage.
|
||||
black.sell.rating,Évaluation {0} %
|
||||
black.mine.sale,{0} réf. {1} prix {2} (x{3}) : {4}
|
||||
black.sale.Listed,en vente
|
||||
black.sale.Paid,payé
|
||||
black.sale.Lost,"rug pull de la plateforme, perdu"
|
||||
black.sale.Delisted,retiré
|
||||
black.sale.Delisted.fake,l'acheteur a repéré la contrefaçon et l'a renvoyé
|
||||
black.kind.gpunew,GPU neuf
|
||||
merchant.GpuNew,Cartes graphiques neuves
|
||||
merchant.GpuUsed,Cartes graphiques d'occasion
|
||||
merchant.Arms,Armes
|
||||
merchant.Docs,Cartes d'accès et puces
|
||||
merchant.Pharma,Pharma
|
||||
merchant.Bulk,En gros
|
||||
black.days,Livraison : {0} j
|
||||
black.sell.listedall,Objets mis en vente : {0}.
|
||||
merchant.Rigs,Plateformes et énergie
|
||||
merchant.Modules,Modules
|
||||
merchant.GunMods,Pièces d'armurerie
|
||||
merchant.Chem,Produits chimiques
|
||||
merchant.Brewer,Brasserie
|
||||
merchant.Farm,Hydroponie
|
||||
merchant.Husbandry,Élevage
|
||||
merchant.Miner,Matériel minier
|
||||
merchant.Water,Eau
|
||||
merchant.Storage,Stockage
|
||||
merchant.Tools,Outils
|
||||
merchant.Luxury,Luxe
|
||||
black.kind.Goods,Marchandises
|
||||
merchant.Elite,Boutique d'élite
|
||||
merchant.Personal,Vendeur particulier
|
||||
black.pay.confirm,Facture
|
||||
black.pay.to,Adresse bénéficiaire : {0}
|
||||
black.pay.cancel,Annuler
|
||||
pay.mix,Mixeur {0} {1}
|
||||
pay.swap,Comptoir Ponero {0} {1}
|
||||
black.edit.cancel,Annuler
|
||||
merchant.Platform,Plateforme
|
||||
black.platform.line,Spot plateforme livraison immédiate
|
||||
black.orders.in,Achats
|
||||
black.orders.out,Ventes
|
||||
black.desk.pair,PONERO [monnaie de confidentialité] prix {0}
|
||||
black.pay.amount,Montant : {0} {1} (environ {2} crédits)
|
||||
black.pay.wallet,Payer depuis le portefeuille
|
||||
hw.total,Total ≈ {0} crédits
|
||||
hw.pending.bill,À payer : {0}
|
||||
hw.pending.sign,À signer : {0}
|
||||
hw.send,Envoyer
|
||||
hw.review,Demande de signature
|
||||
hw.to,Adresse bénéficiaire
|
||||
hw.avail,Disponible {1} {0}
|
||||
hw.amount,Montant
|
||||
hw.bill,Facture : {0} {1} {2}
|
||||
hw.fill,Remplir selon facture
|
||||
hw.next,✓ Suivant × Retour
|
||||
hw.err.format,Format d'adresse invalide.
|
||||
hw.err.checksum,Échec de la somme de contrôle de l'adresse.
|
||||
hw.err.self,Il s'agit de l'adresse de ce portefeuille.
|
||||
hw.err.asset,La facture requiert {0}.
|
||||
hw.err.short,Inférieur à la facture : {0} {1}.
|
||||
hw.err.nobill,Aucune facture impayée pour ce bénéficiaire.
|
||||
hw.review.h,Vérification
|
||||
hw.contract,Appel de contrat
|
||||
hw.review.to,Adresse bénéficiaire
|
||||
hw.review.amount,{0} {1} (environ {2} crédits)
|
||||
hw.review.bill,Facture : {0}
|
||||
hw.review.unknown,Aucun historique de transaction à cette adresse.
|
||||
hw.review.over,Paiement excédentaire de {0} {1} ; non remboursé.
|
||||
hw.hold,Maintenir ✓ pour signer × Rejeter
|
||||
hw.tx.h,Transaction
|
||||
hw.tx.signing,Signature en cours…
|
||||
hw.tx.mempool,Diffusée ; en attente dans la mempool…
|
||||
hw.tx.packed,Incluse dans le bloc #{0}
|
||||
hw.tx.confirm,Bloc #{0} confirmation {1}/{2}
|
||||
hw.skip,Passer
|
||||
hw.done.h,Confirmé
|
||||
hw.done.block,Bloc #{0}
|
||||
hw.done.sent,{0} {1} → {2}
|
||||
hw.done.void,Personne n'utilise cette adresse. Les pièces sont perdus.
|
||||
hw.back,Retour
|
||||
hw.rejected,Signature rejetée sur le portefeuille.
|
||||
hw.wait,Confirmez sur le portefeuille.
|
||||
hw.swap,Échanger {0} {1} → environ {2} {3}
|
||||
tab.wallets,Portefeuilles
|
||||
hw.wallet.n,Portefeuille {0}
|
||||
hw.review.own,Portefeuille personnel : {0}
|
||||
hw.review.poinbase,Adresse de dépôt Poinbase
|
||||
poin.deposit,Adresse de dépôt : {0}
|
||||
wallets.count,Portefeuilles {0}/{1}
|
||||
wallets.col.name,Nom
|
||||
wallets.col.addr,Adresse
|
||||
wallets.col.taint,Contamination
|
||||
wallets.open,Ouvrir
|
||||
wallets.use,Connecter
|
||||
wallets.current,Connecté
|
||||
wallets.added,{0} ajouté : {1}
|
||||
nightlog.drained,"Les pièces de {0} ont été transférées, soit environ {1} crédits."
|
||||
item.hwwallet.name,Portefeuille matériel PLEDGER
|
||||
item.hwwallet.desc,Portefeuille matériel à grand écran. Glissez-le sur le terminal de trading pour ajouter un portefeuille (jusqu'à 5).
|
||||
poin.empty,Le compte est vide.
|
||||
hw.copy,Copier
|
||||
hw.paste,Coller
|
||||
hw.copied,Adresse copiée.
|
||||
hw.copied.addr,{0} copié
|
||||
hw.balance.frozen," (gelé {0})"
|
||||
wallets.destroy,Détruire
|
||||
wallets.destroy.sure,Confirmer
|
||||
wallets.destroyed,{0} détruit : {1}
|
||||
wallets.destroy.warn,Détruire {0} fait perdre définitivement ses pièces. Appuyez à nouveau pour confirmer.
|
||||
payout.label,Versement
|
||||
payout.unset,Non défini
|
||||
payout.set,Définir l'adresse
|
||||
payout.h,Adresse de versement
|
||||
payout.cur,Actuelle : {0}
|
||||
payout.pick,Portefeuilles personnels :
|
||||
payout.manual,Ou saisissez une adresse :
|
||||
payout.clear,Effacer
|
||||
payout.err,Adresse invalide.
|
||||
nightlog.mined.lost,"{0} PSC minés perdus : aucune adresse de versement définie, ou son portefeuille a été détruit."
|
||||
wallets.none,Aucun portefeuille chargé. Glissez un portefeuille matériel sur le terminal.
|
||||
web3.err.noconn,Aucun portefeuille connecté.
|
||||
web3.connect,Connecter le portefeuille
|
||||
web3.disconnect,Déconnecter
|
||||
web3.conn,{0} {1}
|
||||
hw.balance.value,≈ {0}
|
||||
wallets.rename,Renommer
|
||||
wallets.rename.h,Nouveau nom pour {0}
|
||||
wallets.rename.ok,OK
|
||||
hw.fee.slow,Lent
|
||||
hw.fee.normal,Normal
|
||||
hw.fee.fast,Rapide
|
||||
hw.fee,Frais de gas {0} {1} (environ {2} crédits)
|
||||
hw.confs,{0} confirmations requises
|
||||
hw.congested,Réseau saturé
|
||||
hw.congested.slow,Réseau saturé : les frais lents risquent d'être évincés de la mempool
|
||||
hw.recent,Récent
|
||||
hw.recent.out,→ {0} {1} {2}
|
||||
hw.recent.in,← {0} {1} {2}
|
||||
hw.review.history,Adresse dans votre historique
|
||||
hw.tx.stuck,En attente dans la mempool…
|
||||
hw.tx.dropped,Retirée de la mempool. Rien n'a été envoyé ; les frais de gas sont débités.
|
||||
hw.dropped.h,Non envoyé
|
||||
hw.err.fee,Solde insuffisant pour payer les frais de gas.
|
||||
news.congest.title,Congestion de la chaîne
|
||||
news.congest.desc,Une ruée sur un airdrop a saturé la chaîne. Les frais de gas ont explosé et les transactions à faibles frais risquent d'être évincées de la mempool.
|
||||
news.phish.title,Avis Poinbase : migration de l'adresse de dépôt
|
||||
news.phish.desc,Poinbase a mis à niveau son système de portefeuilles. L'ancienne adresse de dépôt sera désactivée ; veuillez envoyer vos actifs à la nouvelle adresse {0}.
|
||||
black.forum.phish,"Quelqu'un a publié la nouvelle adresse du mixeur : {0}, affirmant que l'ancienne est sous surveillance."
|
||||
hw.gas,Gas ×{0}
|
||||
web3.sub.stake,Staking
|
||||
stake.h,Pool de staking de la Révolution
|
||||
stake.rate,Taux quotidien {0}% ; attente de retrait : {1} jours sans intérêt
|
||||
stake.low,Couverture de réserve faible ; taux réduit
|
||||
stake.cra,Prix CRA {0} {1}
|
||||
stake.none,Aucun staking.
|
||||
stake.col.wallet,Portefeuille
|
||||
stake.col.amount,Staké
|
||||
stake.col.queue,Déverrouillage
|
||||
stake.day," (jour {0})"
|
||||
spark.price,Jeton d'équilibre SPARK {0} crédits
|
||||
stake.ops,{0}
|
||||
stake.avail,CRA {0} Staké {1}
|
||||
stake.do,Staker
|
||||
stake.undo,Demander un retrait
|
||||
stake.sum.in,Staker {0} CRA
|
||||
stake.sum.out,Demander le retrait de {0} CRA (disponible dans {1} jours)
|
||||
stake.done.in,{0} CRA stakés.
|
||||
stake.done.out,Retrait de {0} CRA demandé ; retour au portefeuille le jour {1}.
|
||||
nightlog.stakeint,Intérêts de staking +{0} CRA.
|
||||
nightlog.unstaked,Les {0} CRA retirés du staking sont revenus sur {1}.
|
||||
news.crawarn.title,Troubles au pool de staking de la Révolution
|
||||
news.cralow.title,La Révolution réduit le taux de staking
|
||||
stake.avail2,SPARK {0}
|
||||
poin.sub.spot,Spot
|
||||
poin.sub.perp,Perps
|
||||
perp.h,Contrats perpétuels
|
||||
perp.acct,Compte sur marge CRC {0}
|
||||
perp.debt,Dette {0} ; saisie des objets dans {1} jour(s). Nouvelles positions et retraits bloqués jusqu'au remboursement.
|
||||
perp.banned,Compte perpétuel banni : encore {0} jour(s).
|
||||
perp.none,Aucune position.
|
||||
perp.col.pos,Position
|
||||
perp.col.notional,Valeur notionnelle
|
||||
perp.col.price,Entrée → prix
|
||||
perp.col.pnl,PnL
|
||||
perp.col.liq,Prix liq.
|
||||
perp.long,Long
|
||||
perp.short,Short
|
||||
perp.rate,{0} prix {1} financement {2} %/nuit
|
||||
perp.fund,Fonds d'assurance {0}
|
||||
perp.open,Ouvrir
|
||||
perp.margin,Montant de la marge (CRC)
|
||||
perp.do.open,Ouvrir
|
||||
perp.do.add,+ Marge
|
||||
perp.do.close,Fermer
|
||||
perp.opened,"Position {0} {1} ouverte : marge {2} CRC, {3}×."
|
||||
perp.added,{0} CRC de marge ajoutés.
|
||||
perp.closed,Fermée ; {0} CRC reversés sur le compte (PnL {1}).
|
||||
perp.deficit,"Déficit de capital de {0}, couvert par le fonds d'assurance et la dette."
|
||||
perp.err.Banned,Le compte perpétuel est banni.
|
||||
perp.err.Debt,Vous avez une dette ; ouverture de position interdite.
|
||||
perp.err.Leverage,Le levier dépasse la limite de ce produit.
|
||||
perp.err.Size,Plafond de position dépassé pour ce produit.
|
||||
perp.err.Funds,Solde CRC insuffisant sur le compte (frais inclus).
|
||||
perp.err.Opposite,Impossible d'être long et short sur le même produit ; fermez d'abord.
|
||||
perp.err.NoPosition,Aucune position.
|
||||
perp.err.Margin,Saisissez un montant de marge.
|
||||
perp.debt.block,Dette envers le comptoir des perpétuels ; retraits bloqués.
|
||||
nightlog.perp.liq,{0} a été liquidé ; la marge de {1} est perdue.
|
||||
nightlog.perp.adl,Fonds d'assurance épuisé ; {0} a subi un désendettement auto et cédé {1} de profit.
|
||||
nightlog.perp.interest,Intérêts courus sur la dette de contrats perpétuels ; vous devez désormais {0}.
|
||||
nightlog.perp.seize,Dette de contrats perpétuels en souffrance : les objets saisis ont couvert {0}.
|
||||
nightlog.perp.writeoff," {0} passés en perte ; le compte de contrats perpétuels est banni pour {1} jours."
|
||||
perp.slip.title,Bordereau de saisie de dette perpétuelle
|
||||
perp.preview2,Frais {0} liq. {1}
|
||||
nightlog.perp.repaid,Déficit de contrats perpétuels : {0} CRC ont été prélevés sur le compte Poinbase pour le remboursement.
|
||||
perp.err.Thin,Le glissement sur cet ordre est si élevé qu'il entraînerait une liquidation immédiate. Réduisez le montant ou le levier.
|
||||
perp.err.Single,Une seule position à la fois ; ajoutez de la marge.
|
||||
mat.hypertech_electronic,Composant électronique hypertech
|
||||
item.asic.name,Mineur (machine) RatDigg {0}
|
||||
item.asic.dead.name,Mineur (machine) RatDigg {0} grillé
|
||||
item.asic.desc,"Taux de hachage nominal {0} GH/s. Consommation nominale {1} kJ/j. État {2}. Mineur (machine) autonome : nécessite une batterie pour fonctionner, accepte des modules."
|
||||
item.asic.dead.desc,Grillé. Glissez des composants électroniques dessus pour le réparer : actuellement {0} × {1}. Santé −20 une fois réparé.
|
||||
item.asic.dead.fixed,Déjà réparé.
|
||||
merchant.Asic,Dealeur de mineurs (machine)
|
||||
black.kind.asic,Mineur (machine) état {0} %
|
||||
black.kind.asicnew,Mineur (machine) neuf
|
||||
news.erawarn.title,RatDigg s'apprête à lancer une nouvelle génération de mineurs (machine)
|
||||
news.erawarn.desc,"Le fabricant de mineurs dédiés a annoncé un nouveau matériel, et le secteur s'attend à ce que les grandes fermes renouvellent leur parc sous peu. Certains disent que les beaux jours du minage par carte graphique sont comptés."
|
||||
news.era.title,L'ère des mineurs (machine)
|
||||
news.era.desc,Une nouvelle génération de mineurs dédiés est produite en masse et les grandes fermes ont réduit leurs coûts d'électricité de moitié. Le taux de hachage du réseau va grimper et les gains des mineurs sur carte graphique seront dilués.
|
||||
web3.sub.predict,Prédictions
|
||||
predict.h,Marchés de prédiction
|
||||
predict.acct,{0} : CRC {1}
|
||||
predict.none,Aucun marché ouvert aujourd'hui.
|
||||
predict.closed,fermé
|
||||
predict.row,Oui {0} Non {1}
|
||||
predict.held,"détient {0} x{1}, coût {2}"
|
||||
predict.yes,Oui
|
||||
predict.no,Non
|
||||
predict.void,annulé
|
||||
predict.result,Jour {0} {1} résultat : {2} {3}
|
||||
predict.pick,Trader
|
||||
predict.price,Prix par part : Oui {0} Non {1}
|
||||
predict.pos,{0} : {1} x{2}
|
||||
predict.pos2,Coût {0} gain {1}
|
||||
predict.sum.buy,Achat de {1} pour {2} CRC : {0}
|
||||
predict.sum.sell,Vente de position de prédiction : {0}
|
||||
predict.closed.note,"Fermé, en attente de règlement."
|
||||
predict.preview,"Acheter {0} : env. {1} parts (moy. {2}), net {3} si correct"
|
||||
predict.buy.yes,Acheter Oui
|
||||
predict.buy.no,Acheter Non
|
||||
predict.sell,Tout vendre
|
||||
predict.bought,"Achat de {0} pour {2}, rapporte {1} si correct."
|
||||
predict.sold,"Vendu, reçu {0}."
|
||||
predict.err.Closed,Ce marché est fermé.
|
||||
predict.err.Amount,Montant non valide.
|
||||
predict.err.Funds,Pas assez de CRC dans le portefeuille.
|
||||
predict.err.Cap,Limite de position dépassée pour ce marché.
|
||||
predict.err.Opposite,Vous détenez la position inverse ; vendez-la d'abord.
|
||||
predict.err.NoPosition,Aucune position sur ce marché.
|
||||
predict.win.one,Jour {0}
|
||||
predict.win.range,Jours {0}-{1}
|
||||
predict.q.event,"{0} : ""{1}"" se produit"
|
||||
predict.q.faction,{0} : {1} lance une opération
|
||||
predict.q.purity,{0} : pureté de {1} >= {2}
|
||||
predict.q.price,{0} : prix de {1} >= {2}
|
||||
predict.faction.FACTION_SECURITY,Sécurité
|
||||
predict.faction.FACTION_REVOLUTION,Révolution
|
||||
predict.faction.FACTION_LOWER_LEVEL,Niveau inférieur
|
||||
predict.faction.FACTION_UPPER_LEVEL,Niveau supérieur
|
||||
predict.faction.FACTION_BLACK_MARKET,Marché noir
|
||||
predict.purity.gutter,Eau du niveau inférieur
|
||||
predict.purity.rust,Eau du niveau supérieur
|
||||
nightlog.predict.win,"Prédiction correcte : ""{0}"", {1} versés."
|
||||
nightlog.predict.lose,"Prédiction incorrecte : ""{0}"", mise de {1} perdue."
|
||||
nightlog.predict.void,"Prédiction annulée : ""{0}"", mise de {1} remboursée."
|
||||
nightlog.predict.caught,"Pari d'initié détecté : ""{0}"", mise et gains de {1} confisqués, fraude inscrite au dossier."
|
||||
predict.tab.markets,Marchés
|
||||
predict.tab.intel,Infos secrètes
|
||||
predict.acct.crt,{0} : CRT {1}
|
||||
predict.tier.0,bas
|
||||
predict.tier.1,moyen
|
||||
predict.tier.2,élevé
|
||||
predict.clue.tip,Tuyau ({0}) : indique {1}
|
||||
predict.clue.queued,Programmé : débute jour {0}
|
||||
predict.clue.queued2,"Programmé : jour {0} ""{1}"""
|
||||
predict.clue.cool,Événement en cours ou en recharge
|
||||
predict.clue.busy,Opération de faction en cours ; pas de nouvelle avant un moment
|
||||
predict.clue.halving,Halving au jour {0} ; l'ancrage monte la semaine précédente
|
||||
predict.clue.anchor,Prix d'ancrage actuel : {0}
|
||||
predict.clue.gas,Gas récent : {0}
|
||||
predict.clue.drain,Consommation par nuit : {0}
|
||||
predict.clue.era,"Aléatoire entre les jours {0}-{1}, annoncé d'avance"
|
||||
predict.clue.era.warned,Annoncé : débute aux jours {0}-{1}
|
||||
predict.q.gas,{0} : indice de gas >= {1}
|
||||
predict.q.cra,{0} : alerte CRA émise
|
||||
predict.q.era,{0} : début de l'ère ASIC
|
||||
predict.era,Ère ASIC
|
||||
predict.pos3,Moy. {0} actuel {1}
|
||||
predict.pos4,Vendre maintenant rapporte {0}
|
||||
intel.h,Courtier en infos secrètes
|
||||
intel.locked,Nécessite la boutique Web3 et une réputation au Marché noir de {0}.
|
||||
intel.brief.buy,Acheter le point de situation ({0} CRT)
|
||||
intel.brief.none,Aucun point de situation acheté pour le moment.
|
||||
intel.brief.day,Point de situation du jour {0}
|
||||
intel.tips.h,Tuyaux d'initié
|
||||
intel.tips.none,Rien à demander (uniquement opérations de faction et ère ASIC).
|
||||
intel.tip.buy,Précision env. {0} % {1} CRT
|
||||
intel.err.funds,"Pas assez de CRT dans le portefeuille, ou le marché n'est plus disponible à l'achat."
|
||||
intel.brief.sum,"Point de situation, {0} CRT"
|
||||
intel.tip.sum,Tuyau d'initié {0} CRT : {1}
|
||||
intel.brief.done,Point de situation obtenu.
|
||||
intel.tip.done,On raconte : {0}.
|
||||
predict.brief.levels,Sécurité {0} Rév {1} Marché noir {2} Troubles {3} Niveau sup. {4}
|
||||
predict.brief.busy,{0} : opération en cours
|
||||
predict.brief.queued,{0} : opération programmée
|
||||
predict.brief.none,{0} : rien à lancer
|
||||
predict.brief.can,{0} : peut lancer {1}
|
||||
predict.clue.push,Vous avez fait bouger le prix de {0} % : risqué
|
||||
nightlog.predict.manip,"Prédiction jugée comme manipulation de marché : ""{0}"", mise de {1} confisquée, fraude inscrite au dossier."
|
||||
news.manip.title,La bourse enquête sur des transactions inhabituelles
|
||||
news.manip.desc,Les régulateurs signalent que des ordres au comptant massifs ont servi à faire bouger les prix pour tirer profit des dérivés et des prédictions ; les fonds ont été saisis.
|
||||
perp.manip,Le profit de clôture de {0} a été jugé comme manipulation de marché et confisqué ; compte de contrats perpétuels gelé pour {1} jours.
|
||||
web3.sub.ponzi,Rendement
|
||||
ponzi.h,Système de Ponzi
|
||||
ponzi.acct,Portefeuille émetteur {0} : CRC {1}
|
||||
ponzi.rate,Taux quotidien {0} %
|
||||
ponzi.pool,Pool {0} / plafond {1}
|
||||
ponzi.inflow,Nouveaux dépôts hier soir : {0}
|
||||
ponzi.interest,Intérêts dus ce soir : {0}
|
||||
ponzi.own,Intérêts payés de votre poche : {0}
|
||||
ponzi.wind,Risque de dénonciation : {0}
|
||||
ponzi.wind.low,faible
|
||||
ponzi.wind.mid,moyen
|
||||
ponzi.wind.high,élevé
|
||||
ponzi.idle,Aucun système de Ponzi émis.
|
||||
ponzi.done,Le système est fermé ; un seul par sauvegarde.
|
||||
ponzi.ops,Actions
|
||||
ponzi.rug,Rug pull du pool ({0})
|
||||
ponzi.rug.confirm,Cliquez à nouveau pour confirmer le rug pull de {0}
|
||||
ponzi.rugged,"{0} emportés, totalement contaminés."
|
||||
ponzi.open,Lancer un système de Ponzi
|
||||
ponzi.ad,Frais marketing de {0} CRC prélevés sur le portefeuille actuel ; signature requise.
|
||||
ponzi.start,Lancer
|
||||
ponzi.started,Lancé.
|
||||
ponzi.err,Pas assez de CRC dans le portefeuille pour les frais marketing.
|
||||
nightlog.ponzi.collapse,"Le système n'a pas pu verser les intérêts ; ruée sur le pool, pool de {0} confisqué, fraude inscrite au dossier, réputation au Niveau inférieur réinitialisée."
|
||||
nightlog.ponzi.reported,"Le système a été dénoncé ; pool de {0} confisqué, fraude inscrite au dossier, réputation au Niveau inférieur réinitialisée."
|
||||
news.ponzi.title,Effondrement d'un système de Ponzi
|
||||
news.ponzi.desc,Un système de Ponzi géré dans le Niveau inférieur a été dénoncé ; les investisseurs ont afflué et les régulateurs ont gelé les fonds.
|
||||
news.ponzi.rug.title,Arnaque à l'investissement
|
||||
news.ponzi.rug.desc,L'opérateur d'un système de Ponzi s'est enfui avec tous les fonds ; les investisseurs du Niveau inférieur ont tout perdu.
|
||||
ponzi.start.sum,"Lancer un système de Ponzi, taux quotidien {0} %, marketing {1} CRC"
|
||||
ponzi.rug.sum,Rug pull du pool {0}
|
||||
ponzi.err.wallet,Signer avec le portefeuille émetteur.
|
||||
predict.clue.counter,"Infos secrètes : planifié (informateur du comptoir, mot de rumeur)"
|
||||
web3.sub.airdrop,Airdrops
|
||||
air.h,Airdrops
|
||||
air.none,Aucun airdrop à réclamer pour le moment.
|
||||
air.row,{0} récompense {1} CRC {2} jusqu'au jour {3}
|
||||
air.claim,Réclamer
|
||||
air.unlimited,approuver {0} sans limite
|
||||
air.limited,approuver {0} {1}
|
||||
air.approvals,Approbations de {0}
|
||||
air.approvals.none,Aucune approbation.
|
||||
air.approval,{0} : {1}
|
||||
air.revoke,Révoquer
|
||||
air.sum,Réclamer l'airdrop {0} ({1})
|
||||
air.claimed,Reçu {0} CRC.
|
||||
air.auth,Autoriser le portefeuille
|
||||
air.unauth,Non autorisé
|
||||
air.authed,Autorisé : {0}
|
||||
air.authed.msg,Portefeuille autorisé pour {0}.
|
||||
air.auth.sum,Autoriser {0} à agir pour ce portefeuille. Portée : {1}.
|
||||
air.err.unauth,Autorisez d'abord le portefeuille pour cet airdrop.
|
||||
air.revoke.sum,Révoquer l'approbation {1} de {0}
|
||||
air.revoked,Approbation révoquée.
|
||||
air.err.wallet,Signer avec le portefeuille ayant approuvé.
|
||||
pool.h,Pools de rendement tiers (CRC)
|
||||
pool.none,Aucun pour le moment.
|
||||
pool.col.name,Pool
|
||||
pool.col.rate,Taux/j
|
||||
pool.col.reserve,Réserve
|
||||
pool.col.lock,Blocage
|
||||
pool.col.audit,Audit
|
||||
pool.col.mine,Mon dépôt
|
||||
pool.yes,oui
|
||||
pool.no,non
|
||||
pool.pending,retrait en cours
|
||||
pool.closed,(fermé)
|
||||
pool.deposit,Dépôt
|
||||
pool.withdraw,Retrait
|
||||
pool.withdraw.lock,Demander le retrait ({0} j)
|
||||
pool.err.cap,Plafond du pool dépassé ; {0} restant.
|
||||
pool.err.none,Aucun dépôt.
|
||||
pool.sum.in,Dépôt sur {0} : {1} CRC
|
||||
pool.sum.out,Retirer {1} CRC de {0}
|
||||
pool.done.in,{0} CRC déposés sur {1}.
|
||||
pool.done.out,{0} CRC retirés.
|
||||
pool.done.lock,"Retrait de {0} CRC demandé, arrivée au jour {1}."
|
||||
nightlog.scam.drain,"{1} {2} de {0} ont été siphonnés par ""{3}"" via une approbation."
|
||||
nightlog.scam.rug,"Le pool de rendement ""{0}"" a fait un rug pull ; les {1} CRC de {2} ont disparu."
|
||||
nightlog.scam.dry,"Le pool de rendement ""{0}"" a épuisé ses réserves et a fermé ; {1} CRC restitués à {2}."
|
||||
nightlog.scam.paid,"Le retrait de ""{0}"" est arrivé : {2} a reçu {1} CRC."
|
||||
nightlog.scam.fakepay,Virement falsifié : {0}
|
||||
nightlog.scam.sent,"Les {0} {1} envoyés à l'adresse sécurisée du ""support"" ont fini chez un escroc."
|
||||
coinpay.intro,Je paie en {0} ; la confirmation sur la chaîne prend un moment.
|
||||
coinpay.intro.fake,"J'ai déjà envoyé les {0}, voici la capture d'écran. Donne la marchandise, je suis pressé."
|
||||
coinpay.fake.entry,{0} a pris {1} en affirmant avoir payé {2} crédits en pièces ; aucune transaction sur la chaîne.
|
||||
scam.support.name,Support Poinbase
|
||||
scam.support.1,"Bonjour, ici le support Poinbase. Nous avons détecté une connexion anormale sur votre compte et celui-ci a été signalé."
|
||||
scam.support.2,Veuillez envoyer aujourd'hui {0} CRC à l'adresse sécurisée {1} pour vérification ; ils seront restitués immédiatement après.
|
||||
scam.support.3,"Sinon, le compte sera gelé définitivement. Je dois filer, n'oubliez pas d'effectuer l'envoi."
|
||||
predict.sold.caught,"Délit d'initié détecté lors de la vente : mise et profits confisqués, fraude inscrite au dossier."
|
||||
predict.row.move," (la nuit dernière {0} {1})"
|
||||
predict.stats.h,Historique (prix ouv. moy. / taux réel)
|
||||
predict.stats.row,"{0} : {1} marchés, ouv. moy. {2}, survenu {3} %"
|
||||
predict.kind.Event,Événements d'actualité
|
||||
predict.kind.Faction,Opérations de faction
|
||||
predict.kind.Purity,Pureté de l'eau
|
||||
predict.kind.Price,Prix du PSC
|
||||
predict.kind.Gas,Gas
|
||||
predict.kind.Cra,Alerte CRA
|
||||
predict.kind.Era,Ère ASIC
|
||||
nightlog.predict.move,"Prédiction ""{0}"" : {1} -> {2}"
|
||||
nightlog.predict.why," ({0})"
|
||||
chart.empty,Graphique journalier {0} : aucun historique ; enregistrement à partir d'aujourd'hui.
|
||||
chart.caption,{0} journalier H {2} B {3} C {4} ({5} %)
|
||||
chart.legend,"<size=80%>vert hausse, rouge baisse ; jaune MM 7j ; barres : gris marché / cyan vous</size>"
|
||||
chart.legend.thr,"<size=80%>vert hausse, rouge baisse ; jaune MM 7j ; tirets bleus seuil</size>"
|
||||
news.story.serpico_rev.title,La Révolution détient des dossiers sur la Sécurité
|
||||
news.story.serpico_rev.desc,"La Révolution aurait obtenu des preuves de corruption au sein de la Sécurité. Selon le pool de staking : une forte somme a été injectée dans la réserve de la Révolution, et le SPARK se raffermit."
|
||||
news.story.serpico_bm.title,Le Marché noir conclut un accord discret
|
||||
news.story.serpico_bm.desc,"Un document interne de la Sécurité a changé de mains sur le Marché noir. Les règlements sur le Darknet sont nettement plus stables depuis, et les remboursements en CRT n'ont pas failli une seule fois."
|
||||
news.story.serpico_sec.title,La Sécurité lance une purge interne
|
||||
news.story.serpico_sec.desc,La Sécurité a annoncé une enquête approfondie sur la corruption interne et une surveillance accrue des flux financiers. Poinbase durcit l'examen des retraits et les services de mixeur ont été ciblés.
|
||||
news.story.eleanor_leak.title,Fuite des données de sélection de Nutrifruit
|
||||
news.story.eleanor_leak.desc,"Le journal du Niveau inférieur a publié des recherches permettant au Nutrifruit de donner à nouveau des graines ; l'action Pastelle s'est effondrée. La banque dépositaire des fonds du Niveau supérieur signale des créances douteuses, et la Révolution gagne du terrain."
|
||||
news.story.eleanor_return.title,Pastelle récupère les données dérobées
|
||||
news.story.eleanor_return.desc,"Pastelle a confirmé la récupération des données de recherche dérobées. Le capital du Niveau supérieur pousse un soupir de soulagement, et la notation de la banque dépositaire de CRC a été rehaussée."
|
||||
news.story.lun_arrested.title,L'Agent Lun arrêté pour abus de pouvoir
|
||||
news.story.lun_arrested.desc,La Sécurité a arrêté l'Agent Lun sur-le-champ pour abus de pouvoir et promis une répression stricte des échanges illégaux pendant les deux prochaines semaines.
|
||||
tumbler.name,Tumbler
|
||||
tumbler.v1.1,Salut. J'ai entendu dire que le terminal ici est relié à mon mixeur.
|
||||
tumbler.v1.2,C'est moi qui ai codé ce truc. On m'appelle Tumbler.
|
||||
tumbler.v1.3,Il ne touche pas à ta marchandise et ne tient pas tes comptes. Il brasse juste les pièces.
|
||||
tumbler.v1.4,Je passais par là. Je voulais voir à quoi ressemblent mes utilisateurs.
|
||||
tumbler.v2.1,Ça commence à chauffer. La Sécurité s'en prend aux services de mixeur sur la chaîne.
|
||||
tumbler.v2.2,Ils ont signalé plusieurs grosses adresses et sont remontés jusqu'à mon nœud.
|
||||
tumbler.v2.3,"Si le mixeur s'arrête quelques jours, pas de panique. Les pièces bloquées dedans ne seront pas perdues."
|
||||
tumbler.v3.1,"Ils ont coupé mon nœud. Tôt ou tard, ils trouveront où j'habite."
|
||||
tumbler.v3.2,J'ai un disque de clés contenant les clés de signature du mixeur.
|
||||
tumbler.v3.3,"Si la Sécurité met la main dessus, ils pourront reconstituer l'historique de chaque utilisateur. Le tien aussi."
|
||||
tumbler.v3.ask,Tu peux me le cacher pendant quelques jours ?
|
||||
tumbler.v3.choice.hide,[Prendre le disque et le cacher]
|
||||
tumbler.v3.choice.report,"[Accepter, puis prévenir la Sécurité]"
|
||||
tumbler.v3.choice.sell,[Prendre le disque et le vendre au Marché noir]
|
||||
tumbler.v3.thanks1,Merci. Je repasserai le chercher dans quelques jours.
|
||||
tumbler.v3.thanks2,"Ne le laisse pas traîner. S'ils tombent dessus pendant une fouille, on est tous les deux foutus."
|
||||
tumbler.v3.report1,... D'accord. Je repasserai plus tard.
|
||||
tumbler.v4.back.1,Je viens récupérer le disque.
|
||||
tumbler.v4.back.2,Le nœud a été déplacé. La Sécurité ne le trouvera pas de sitôt.
|
||||
tumbler.v4.back.3,"Voilà pour le dérangement. Désormais, les frais de mixeur sont à moitié prix pour toi."
|
||||
tumbler.v4.lost.1,Où est le disque ?
|
||||
tumbler.v4.lost.2,... Tu l'as perdu ?
|
||||
tumbler.v4.lost.3,Laisse tomber. Je vais trouver une solution.
|
||||
tumbler.v4.sold.1,"Tu as vendu le disque au Marché noir, pas vrai ?"
|
||||
tumbler.v4.sold.2,"C'est eux qui gèrent le mixeur maintenant. Les frais ont doublé, et l'argent des utilisateurs peut disparaître à tout moment."
|
||||
tumbler.v4.sold.3,Je ne l'oublierai pas.
|
||||
tumbler.v4.none.1,Tant pis. Fais comme si je n'étais jamais venu.
|
||||
item.keydrive.name,Disque de clés
|
||||
item.keydrive.desc,"Un support de données laissé par Tumbler, contenant les clés de signature du mixeur. Contrebande : s'il est découvert lors d'une fouille, il sera inscrit au dossier."
|
||||
mixer.closed,Le mixeur a été arrêté et n'accepte plus de nouveaux dépôts. Les pièces déjà à l'intérieur sont restituées normalement.
|
||||
news.tumbler.sanction.title,La Sécurité saisit un nœud de mixeur
|
||||
news.tumbler.sanction.desc,"La Sécurité a annoncé la saisie d'un nœud d'un service de mixeur sur la chaîne, affirmant qu'il facilitait le blanchiment d'argent. Le service est temporairement interrompu."
|
||||
news.tumbler.caught.title,Arrestation de l'opérateur du mixeur
|
||||
news.tumbler.caught.desc,L'opérateur du mixeur connu sous le nom de Tumbler a été arrêté dans le Niveau inférieur. La Sécurité indique que le service de mixeur a été définitivement fermé.
|
||||
news.tumbler.sold.title,Le service de mixeur change de mains
|
||||
news.tumbler.sold.desc,"Selon certaines sources, les clés de signature d'un service de mixeur du Niveau inférieur sont tombées aux mains du Marché noir, et les frais ont aussitôt augmenté. Les utilisateurs craignent pour leurs fonds."
|
||||
nightlog.tumbler.gift,Tumbler a récupéré le disque de clés et a laissé {0} CRT en remerciement (envoyés à {1}) ; frais du mixeur réduits de moitié.
|
||||
mixer.status.closed,Statut : arrêté
|
||||
yield.sub.pools,Pools de rendement
|
||||
yield.sub.mine,Lancer un Ponzi
|
||||
pool.side.h,Dépôt
|
||||
ponzi.early,Les systèmes de Ponzi peuvent être lancés dès le jour {0}.
|
||||
bpay.h,Paiement
|
||||
bpay.qty,Quantité
|
||||
bpay.total,Total : {0} crédits
|
||||
bpay.need,Payer {0} {1} solde du portefeuille : {2}
|
||||
bpay.invoice,Créer une facture
|
||||
bpay.swap.h,Conversion auto en {0}
|
||||
bpay.swap.none,Aucune autre monnaie du portefeuille n'est suffisante
|
||||
bpay.swap.need,"Payer {0} {1}, inclut {2} % de glissement"
|
||||
bpay.swap.btn,Convertir et payer
|
||||
bpay.swap.sum,"{0} : conversion auto, payer {2} {1}, converti en {3} avant la commande"
|
||||
bpay.back,Retour
|
||||
cart.fab,Panier {0}
|
||||
cart.h,Panier
|
||||
cart.empty,Le panier est vide.
|
||||
cart.added,Ajouté au panier : {0}
|
||||
cart.back,Retour boutique
|
||||
cart.done,Articles payés : {0}.
|
||||
cart.partial,Articles payés : {0} ; {1} en échec (stock ou solde).
|
||||
black.info.accepts,Accepte : {0}
|
||||
black.info.advance.yes,déblocage anticipé accepté
|
||||
black.info.advance.no,pas de déblocage anticipé
|
||||
settings.section.ui,Interface
|
||||
settings.section.story,Histoire
|
||||
settings.section.difficulty,Difficulté
|
||||
settings.terminal_size,Taille du terminal de trading
|
||||
settings.terminal_size_desc,Taille de la fenêtre en unités d'interface (largeur × hauteur). Appliquée à la prochaine ouverture du terminal.
|
||||
settings.tumbler_story,Intrigue Tumbler
|
||||
settings.tumbler_story_desc,"Visites de Tumbler et mission du disque de clés. Désactivée, plus aucune nouvelle visite ; la progression acquise est conservée."
|
||||
settings.risk_scale,Multiplicateur de risque
|
||||
settings.risk_scale_desc,"Multiplie la probabilité d'arnaques, de rug pulls, d'empoisonnement de portefeuille, de détournement d'adresse et d'hameçonnage. S'applique à toutes les sauvegardes."
|
||||
settings.mining_scale,Multiplicateur de gains de minage
|
||||
settings.mining_scale_desc,Multiplie la récompense de bloc versée aux machines de minage. S'applique à toutes les sauvegardes.
|
||||
gg.header,Comité de commerce
|
||||
gg.p1.cap,Carte graphique
|
||||
gg.p1.makers,Deux fabricants courants sont présents sur la station :\n\n - Probidia (« PB »)\n - PMD (« MD »)
|
||||
gg.p1.note,"Quel que soit le fabricant, la valeur d'une carte dépend uniquement du prix catalogue de la puce réelle et de sa santé : à pleine santé elle égale le prix catalogue, à santé 0 il n'en reste que {CardValueFloor:%}."
|
||||
gg.fan.h,Pales
|
||||
gg.fan.0,Propres (prix inchangé)
|
||||
gg.fan.1,Poussiéreuses (-{CardFanDust:%})
|
||||
gg.fan.2,Ébréchées (-{CardFanChipped:%})
|
||||
gg.fin.h,Contacts
|
||||
gg.fin.0,Brillants (prix inchangé)
|
||||
gg.fin.1,Ternes (-{CardFingersDark:%})
|
||||
gg.fin.2,Oxydés (-{CardFingersOxidized:%})
|
||||
gg.brk.h,Équerre
|
||||
gg.brk.0,Intacte (prix inchangé)
|
||||
gg.brk.1,Rayée (-{CardBracketScratch:%})
|
||||
gg.seal.h,Scellé
|
||||
gg.seal.0,Intact (prix inchangé)
|
||||
gg.seal.2,Manquant (-{CardSealMissing:%})
|
||||
gg.wear.note,"Les pales, les contacts et l'équerre se dégradent avec l'usure de chaque nuit et ne font qu'empirer ; le scellé est une caractéristique fixe. L'état influe aussi sur le taux de hachage, l'usure et la probabilité de griller."
|
||||
gg.serial.h,N° de série
|
||||
gg.serial.cap,Dos de la carte (autocollant)
|
||||
gg.serial.pb,"Probidia (« PB »)\n Codes usine valides : 11, 12, 21, 34, 47"
|
||||
gg.serial.md,"PMD (« MD »)\n Codes usine valides : 13, 22, 35, 41, 58"
|
||||
gg.print.h,Sérigraphie dos
|
||||
gg.print.0,Conforme au modèle
|
||||
gg.print.1,Autre modèle (contrefaçon)
|
||||
gg.print.2,"Réimprimé, de travers (contrefaçon)"
|
||||
gg.point.h,Signaler
|
||||
gg.ex.card,"Exemple : {0}, santé {1}%"
|
||||
gg.ex.base,Valeur de base : +{0}
|
||||
gg.ex.fan,Pale ébréchée : -{0}
|
||||
gg.ex.fin,Contacts ternes : -{0}
|
||||
gg.ex.seal,Scellé manquant : -{0}
|
||||
gg.ex.total,Valeur finale : {0}
|
||||
gg.ex.note,Chaque décote est une part de la valeur de base ; elles sont additionnées puis déduites.
|
||||
gg.ex.fan1,Pales poussiéreuses : -{0}
|
||||
gg.ex.fin2,Contacts oxydés : -{0}
|
||||
gg.ex.brk,Équerre rayée : -{0}
|
||||
gg.ex.nodisc,Aucune décote : -0
|
||||
gg.ex.fake,"Annoncé {0}, puce réelle {1} : valeur de la puce réelle"
|
||||
gg.ex.claimed,Prix du modèle annoncé : {0}
|
||||
gg.ex.gap,Écart avec l'offre : {0}
|
||||
gg.ex.h2,Exemple : contrefaçon
|
||||
gg.ex.h3,Exemple : très usée
|
||||
gg.ex.h4,Exemple : peu utilisée
|
||||
gg.ex.h5,Exemple : neuve
|
||||
lbl.price,Prix affiché : {0}
|
||||
lbl.row.count,Ventilateurs
|
||||
lbl.row.pin,Alimentation
|
||||
lbl.count.1,1 ventilateur
|
||||
lbl.count.2,2 ventilateurs
|
||||
lbl.count.3,3 ventilateurs
|
||||
lbl.pin.0,6 broches
|
||||
lbl.pin.1,8 broches
|
||||
lbl.pin.2,2 × 8 broches
|
||||
gg.p1.body,"Les cartes graphiques sont l'élément central de toute plateforme de minage et la marchandise la plus souvent contrefaite sur le marché de l'occasion.\nQuatre points permettent de juger si une carte est authentique : nombre de ventilateurs, connecteur d'alimentation, sérigraphie au dos et numéro de série. Seule une carte conforme à son modèle annoncé sur les quatre points est authentique ; un seul écart suffit pour une contrefaçon.\nLa valeur d'une carte dépend du modèle de la puce réelle et de son état, et chaque trace d'usure fait baisser le prix.\n\nCe guide fournit toutes les connaissances nécessaires pour expertiser une carte graphique."
|
||||
gg.p2.h,Modèles de carte
|
||||
gg.p2.body,Le modèle détermine le nombre de ventilateurs et le connecteur d'alimentation. Une contrefaçon est une puce de modèle inférieur dans le boîtier d'un modèle supérieur ; ses performances et sa valeur sont celles de la puce réelle.
|
||||
gg.tier.0,"RTX 60 / RX 70 : 6 broches, 1 vent."
|
||||
gg.tier.1,"RTX 70 / RX 80 : 8 broches, 2 vent."
|
||||
gg.tier.2,"RTX 80 / RX 800 : 8 broches, 3 vent."
|
||||
gg.tier.3,"RTX 90 / RX 900 : 2 × 8 br., 3 vent."
|
||||
gg.count.h,Nombre de ventilateurs
|
||||
gg.count.body,"Le modèle détermine le nombre de ventilateurs : un ventilateur pour les RTX 60 et RX 70, deux pour les RTX 70 et RX 80, trois pour les RTX 80, RTX 90, RX 800 et RX 900.\nUn nombre de ventilateurs qui ne correspond pas au modèle annoncé indique une contrefaçon."
|
||||
gg.pin.h,Connecteur d'alimentation
|
||||
gg.pin.body,"Le connecteur d'alimentation est lui aussi déterminé par le modèle : 6 broches pour les RTX 60 et RX 70, 8 broches pour les RTX 70, RTX 80, RX 80 et RX 800, 2 × 8 broches pour les RTX 90 et RX 900.\nUn connecteur d'alimentation qui ne correspond pas au modèle annoncé indique une contrefaçon."
|
||||
gg.serial.body,"Le numéro de série figure sur un autocollant au dos, sous la forme : préfixe, code de modèle, tiret, code usine à deux chiffres, tiret et numéro d'ordre à quatre chiffres, par exemple PB2-21-6251."
|
||||
gg.serial.rule,"Les codes de modèle 1 à 4 correspondent à RTX 60 / RX 70, RTX 70 / RX 80, RTX 80 / RX 800 et RTX 90 / RX 900.\nUn code de modèle qui ne correspond pas au modèle (l'autocollant provient de la puce d'origine), ou un code usine ou une longueur non valides (autocollant ajouté après coup), indique une contrefaçon. Le code usine ne sert qu'à vérifier l'authenticité et n'influence pas le prix."
|
||||
gg.print.note,"Une carte n'est authentique que si le nombre de ventilateurs, le connecteur d'alimentation, la sérigraphie et le numéro de série correspondent tous au modèle. Une contrefaçon présente au moins un écart, mais peut imiter correctement les autres points ; chacun doit donc être vérifié."
|
||||
gg.point.body,"S'inspecte à la loupe. Dans la barre d'étiquettes, seule la ligne du modèle possède un bouton « Signaler le modèle » ; les quatre lignes en dessous (ventilateurs, alimentation, sérigraphie dos, n° de série) sont en lecture seule, et chacune des quatre lignes d'état — pales, contacts, équerre, scellé — a son propre « Signaler ».\nSignaler un défaut d'état dissimulé fait passer la ligne à l'état réel et le prix baisse de la différence ; signaler un point exact est rejeté par l'autre partie et la réputation en pâtit.\nSi le nombre de ventilateurs, l'alimentation, la sérigraphie dos ou le n° de série ne correspond pas au modèle annoncé, signalez le modèle : la carte est alors déclarée contrefaçon, le modèle revient à la puce réelle et le prix est recalculé pour cette puce.\n\nLes cartes apportées par les clients de la guilde d'expertise suivent la même règle : les signalements modifient l'estimation jusqu'à l'annonce de la valeur correcte."
|
||||
gg.ex.serial,N° de série : {0}
|
||||
gg.ex.h,"Exemple d'expertise : pale ébréchée, contacts ternes, scellé manquant"
|
||||
rig.label.status,Statut
|
||||
rig.st.cards,Cartes
|
||||
rig.st.power,Conso.
|
||||
rig.st.hash,Hachage
|
||||
rig.st.kj,{0} kJ/j
|
||||
lbl.point.model,Signaler le modèle
|
||||
col.crcprice,Prix en CRC
|
||||
swap.pay,Payer
|
||||
swap.get,Recevoir
|
||||
swap.preview,"Environ {0} {1} {2} pool(s), perte {3} %"
|
||||
swap.go,Échanger
|
||||
swap.same,Les monnaies payée et reçue doivent différer.
|
||||
mint.need,Nécessite {0} CRC et {1} SPARK
|
||||
mint.reserve,Couverture {0} % Collatéral {1} %
|
||||
mint.queue,Ordres en attente
|
||||
mint.order,"{0} {1} CRA, jour {2}"
|
||||
stake.coin,Monnaie déposée
|
||||
stake.sum.via,Échanger {0} {1} → environ {2} CRA puis staker
|
||||
nightlog.cra.lost,L'émetteur n'a pas répondu : l'ordre ({1}) de {0} CRA est perdu.
|
||||
news.crawarn.desc,Quelqu'un fait l'inventaire de la réserve de la Révolution ; les CRA stakés pourraient ne pas être remboursés en totalité. Le déblocage prend quatre jours ; certains disent qu'il est temps d'agir.
|
||||
news.cralow.desc,La couverture de la réserve s'amenuise ; la Révolution a réduit le taux de staking du CRA à une fraction.
|
||||
poin.sub.funds,Fonds
|
||||
funds.receive,Dépôt
|
||||
funds.send,Retrait
|
||||
funds.bank,Compte bancaire
|
||||
funds.wallet,Portefeuille
|
||||
funds.to,Adresse de destination
|
||||
funds.go,Envoyer
|
||||
funds.sending,Envoi de {0} {1} vers {2}
|
||||
funds.confirm,Confirmation {0}/{1}
|
||||
funds.done,{0} {1} sont arrivés dans {2}.
|
||||
funds.done.void,"{0} {1} envoyés ; l'adresse n'a pas de propriétaire, les pièces sont perdues."
|
||||
funds.err.addr,Adresse invalide.
|
||||
funds.err.self,C'est l'adresse de dépôt de Poinbase.
|
||||
funds.err.known,Cette adresse n'accepte que les paiements d'une facture.
|
||||
funds.err.fee,Le montant ne couvre pas les frais de gas.
|
||||
wallets.sub.explorer,Explorateur
|
||||
explorer.search,Adresse
|
||||
explorer.all,Récent
|
||||
explorer.none,Aucun transfert.
|
||||
explorer.col.block,Bloc
|
||||
explorer.col.amount,Montant
|
||||
explorer.mixer,Mixeur
|
||||
cra.mint,Frapper
|
||||
cra.burn,Brûler
|
||||
mint.h,Frappe officielle (CRC + SPARK)
|
||||
mint.sum.in,Frapper {0} CRA avec {1} CRC et {2} SPARK ({3}–{4} jours)
|
||||
mint.sum.out,Brûler {0} CRA contre CRC et SPARK ({1} jours)
|
||||
mint.done.in,Ordre de frappe passé ; échéance au jour {0}.
|
||||
mint.done.out,Ordre de brûlage passé ; échéance au jour {0}.
|
||||
nightlog.cra.minted,{0} CRA frappés et stakés ({1}).
|
||||
nightlog.cra.burned,"{0} CRA brûlés : +{1} CRC, +{2} SPARK ({3})."
|
||||
predict.clue.subsidy,"Réserve à {0} % ; à zéro, l'alerte est certaine"
|
||||
air.noapprove,aucune autorisation de jetons
|
||||
tab.gray,Réseau gris
|
||||
wallets.sub.list,Liste
|
||||
entry.web3.l1,Trading décentralisé et rendement
|
||||
entry.mining.l1,État des machines et gains nocturnes
|
||||
entry.gray.l1,Mixeur et boutique
|
||||
entry.wallets.l1,Portefeuilles matériels et explorateur
|
||||
entry.wallets.l2,Portefeuilles {0} / {1}
|
||||
black.sell.add,Ajouter des articles
|
||||
black.sell.back,Retour à la vitrine
|
||||
black.sell.kinds,En vente {0}/{1} types
|
||||
black.sell.have,{0} en vente
|
||||
black.sell.coins,Cryptos acceptées
|
||||
black.sell.off,Retirer
|
||||
black.sell.off.n,Retirer ×{0}
|
||||
black.sell.nocoin,Acceptez au moins une crypto.
|
||||
black.sell.empty,Rien en vente.
|
||||
black.sell.delisted,{0} retiré(s) ; la marchandise est de retour au stockage.
|
||||
black.sell.partial,"{0} mis en vente, {1} n'ont pas pu l'être."
|
||||
black.sell.limit.stack,{0} exemplaires maximum par article.
|
||||
black.sell.limit.kinds,{0} types maximum en même temps.
|
||||
shelf.fab,Étagère {0}
|
||||
delist.fab,Confirmer le retrait {0}
|
||||
black.fee.h,Prêt à mettre en vente
|
||||
black.fee.line,{0} ×{1} · prix {2} ({3})
|
||||
black.fee.total,Frais de mise en vente {0}
|
||||
black.fee.sum,Frais de mise en vente ({0} art.)
|
||||
black.sale.Sold,"vendu, paiement au jour {0} en {1}"
|
||||
explorer.col.day,Jour
|
||||
explorer.day,Jour {0}
|
||||
explorer.pool,Pool RatDigg
|
||||
explorer.desk,Comptoir Ponero
|
||||
black.fee.pay,Payer les frais de mise en vente
|
||||
explorer.col.from,De
|
||||
explorer.col.to,Vers
|
||||
rig.st.cond,État
|
||||
asic.st.dead,Grillé
|
||||
perp.preview,Valeur notionnelle {0} prix moyen est. {1} (glissement {2}%)
|
||||
perp.sim.close,Clôture valeur notionnelle {0} prix moyen est. {1} (glissement {2}%)
|
||||
perp.sim.close2,Frais {0} environ {1} CRC récupérés (P/L {2})
|
||||
trade.sim.sell,La vente donne environ {0} {1} moy. {2} glissement {3}%
|
||||
trade.sim.buy,L'achat coûte environ {0} {1} moy. {2} glissement {3}%
|
||||
trade.amount.unit,Quantité ({0})
|
||||
trade.fee,Frais {0}%
|
||||
trade.sim.thin,Dépasse la liquidité du pool
|
||||
news.wipe.down.title,"{0} chute de {1}% en un jour, {2} traders liquidés"
|
||||
news.wipe.down.desc,"Au cours de la dernière journée, {1} positions longues sur les perps {0} ont été liquidées, pour {2} crédits au total. Le fonds d'assurance de Poinbase s'établit à {3} crédits."
|
||||
news.wipe.up.title,"{0} bondit de {1}% en un jour, {2} traders liquidés"
|
||||
news.wipe.up.desc,"Au cours de la dernière journée, {1} positions courtes sur les perps {0} ont été liquidées, pour {2} crédits au total. Le fonds d'assurance de Poinbase s'établit à {3} crédits."
|
||||
hot.name,Vendeur
|
||||
hot.intro.CRT,"Ça chauffe en ce moment et ce CRT me brûle les doigts. Il me faut du liquide, vite."
|
||||
hot.intro.PSC,"Le portefeuille d'une ferme de minage a changé de main cette nuit. Le PSC est chez moi, et je ne prends que du liquide."
|
||||
hot.intro.PONERO,"Une rançon, en Ponero. Personne ne peut la tracer. Liquide uniquement."
|
||||
hot.offer,"{0} {1}, soit {2} au cours du jour. Donnez-moi {3} en liquide et les pièces sont à vous tout de suite."
|
||||
hot.choice.yes,Accepter
|
||||
hot.choice.no,Refuser
|
||||
hot.say.yes,Marché conclu.
|
||||
hot.say.no,Je n'y touche pas.
|
||||
hot.done,Pièces envoyées. On ne s'est jamais vus.
|
||||
hot.refused,D'autres le prendront.
|
||||
hot.nocash,Vous n'avez même pas le liquide ? Laissez tomber.
|
||||
hot.nowallet,"Aucun portefeuille connecté, où envoyer les pièces ? Laissez tomber."
|
||||
hot.sting,Pas un geste. Sécurité. Achat de fonds volés : le liquide est confisqué et ce sera inscrit à votre dossier.
|
||||
hw.err.poinbase,Poinbase n'accepte pas le {0}.
|
||||
@@ -0,0 +1,980 @@
|
||||
# Probably Decentralized localization table: Japanese (ja)
|
||||
# AI translation, not proofread. Source: en.csv. Format: key,text (text may be quoted; \n is a line break).
|
||||
upgrade.tab,Web3
|
||||
upgrade.title,Web3ガバナンスコミュニティ
|
||||
upgrade.desc,メンバーは取引ターミナル1台、ハードウェアウォレット1台、マイニングリグ1台、RTX 60グラフィックボード1枚、グラフィックボード鑑定ガイドを受け取る。ターミナルには銀行、Poinbase取引所、Web3、マイニング、ウォレットのページがある。追加のボードやリグはジャックソン博士が販売している。
|
||||
item.terminal.name,取引ターミナル
|
||||
item.terminal.desc,ウォレット、Poinbase取引所、夜間マイニングレポート。
|
||||
item.rig.name,マイニングリグ
|
||||
item.rig.desc,グラフィックボードを最大{0}枚搭載可能。ハッシュレート {1} MH/s。消費電力 {2} kJ/日。
|
||||
rig.label.modules,モジュール
|
||||
item.rig.modules,モジュール:ハッシュレート {0}、消費電力 {1}、損耗 {2}。
|
||||
item.rig.next,スロット{0}:{1}をマイニングリグにドラッグ({2}/{3})。
|
||||
mat.common_electronic,汎用電子部品
|
||||
mat.rare_electronic,希少電子部品
|
||||
rig.label.cards,グラフィックボード
|
||||
item.gpu.name,{0} {1}
|
||||
item.gpu.desc,定格ハッシュレート {0} MH/s。定格消費電力 {1} kJ/日。状態:{2}。
|
||||
item.gpu.burnt.name,焼損した{0} {1}
|
||||
item.gpu.burnt.desc,このボードはもう機能しない。
|
||||
term.title,取引ターミナル
|
||||
tab.report,レポート
|
||||
wallet.line,{0}:{1}(約{2}クレジット)
|
||||
wallet.empty,ウォレットは空です。
|
||||
wallet.total,総額:{0}クレジット
|
||||
wallet.taint,汚染額:{0}クレジット
|
||||
trade.amount,数量
|
||||
trade.deposit,クレジットを入金してCRCに交換
|
||||
trade.withdraw,CRCを出金してクレジットに交換
|
||||
trade.pair,{0}/{1}({2})
|
||||
trade.price,価格 {0}
|
||||
trade.buy,購入
|
||||
trade.sell,売却
|
||||
venue.Exchange,Poinbase
|
||||
venue.Dex,DEX
|
||||
venue.Darknet,ダークネット
|
||||
msg.amount,数量を入力してください。
|
||||
msg.balance,残高が不足しています。
|
||||
msg.trade,{0} {1}を支払い、{2} {3}を受け取りました。
|
||||
msg.deposit,{0}クレジットを入金し、CRCに変換しました。
|
||||
msg.cashout,{0}クレジットを受け取りました。税:{1}クレジット。
|
||||
msg.aml_light,コンプライアンス審査:{0}クレジットの汚染資金が保留されました。
|
||||
msg.aml_heavy,コンプライアンス審査:{0}クレジットの汚染資金が没収され、警察に通報されました。
|
||||
report.none,マイニングレポートはまだありません。
|
||||
report.day,{0}日目の夜
|
||||
report.rigs,稼働リグ:{0}/{1}
|
||||
report.hash,ハッシュレート:{0} MH/s(ネットワーク {1} MH/s)
|
||||
report.mined,採掘量:{0} PSC(約{1}クレジット)
|
||||
report.energy,消費電力:{0} kJ
|
||||
report.burnt,焼損ボード:{0}
|
||||
report.price,PSC価格:{0}クレジット
|
||||
nightlog.mined,マイニングリグが{0} PSCを採掘しました。
|
||||
nightlog.burnt,{0}が1枚焼損した。
|
||||
coinpay.line,取引成立。{0} {1}。
|
||||
nightlog.coinpay,コイン決済の客からの代金は計{0}クレジットが精算され、コインはホットウォレットに入った。
|
||||
nightlog.unpowered,{0}台のマイニングリグまたは専用採掘機に電力が供給されていませんでした。
|
||||
news.open.title,PoinbaseにPSCが上場
|
||||
news.open.desc,上層の取引所PoinbaseがPSC/CRCの取引ペアの取り扱いを開始した。ステーション全域でグラフィックボードの需要が高まっている。
|
||||
news.halving.title,PSCのブロック報酬が半減
|
||||
news.halving.desc,採掘人が毎晩獲得できるコインが半減した。
|
||||
appraisal.gpu,グラフィックボード
|
||||
dealer.name,中古ハードウェア取引人
|
||||
dealer.line1.1,マイニングファームの引き揚げ品のボードだ。状態は名前の横に書いてある。
|
||||
dealer.line1.2,何枚かマイニングに使ったやつがある。安く譲るよ。
|
||||
dealer.line1.3,道中で仕入れた品だ。卸値で出すよ。
|
||||
dealer.line2.1,自分の目で確かめてくれ。裏返して背面も見な。
|
||||
dealer.line2.2,保証はねえぞ。よく見てから買っていけ。
|
||||
dealer.line2.3,買う気があるなら、値段は相談に乗るぜ。
|
||||
inspect.flip.back,裏返す
|
||||
inspect.flip.front,表に戻す
|
||||
item.gpu.grade.1,ほぼ新品
|
||||
item.gpu.grade.2,並品
|
||||
item.gpu.grade.3,使用感あり
|
||||
item.gpu.grade.4,重度の使用感
|
||||
point.none.1,どこもおかしくないぞ。見間違いだろ。
|
||||
point.none.2,どこがだ?買わないなら適当なこと言うなよ。
|
||||
point.worn.1,……チッ、確かにそこはあるな。少し値引きしてやるよ。
|
||||
point.worn.2,目ざといな。わかった、この値段でどうだ。
|
||||
point.fake.1,……バレたか。書き換え品だ。中身相応の値段にするよ。
|
||||
point.fake.2,チッ、純正チップじゃねえな。いいぜ、本来のチップの値段にしてやる。
|
||||
lbl.fan.0,ブレード良好
|
||||
lbl.fan.1,ブレードに埃
|
||||
lbl.fan.2,ブレード欠け
|
||||
lbl.fingers.0,光沢あり
|
||||
lbl.fingers.1,くすみ
|
||||
lbl.fingers.2,酸化・腐食
|
||||
lbl.print.0,型番一致
|
||||
lbl.print.1,他型番の印字
|
||||
lbl.print.2,再印字・傾き
|
||||
lbl.said,(売り手の申告:{0})
|
||||
lbl.point,指摘する
|
||||
lbl.edit,修正
|
||||
cust.fake.1,ラベルと違うじゃないか。偽物を売りつける気か?
|
||||
cust.fake.2,型番が一致しないぞ。表示どおりのチップじゃない。
|
||||
cust.worn.1,書いてあることと違うぞ。不具合を隠していただろ。
|
||||
cust.worn.2,ラベルの状態は嘘だな。この値段じゃ買えない。
|
||||
lbl.row.fan,ブレード
|
||||
lbl.row.fingers,端子
|
||||
lbl.row.bracket,ブラケット
|
||||
lbl.row.print,背面印字
|
||||
lbl.row.serial,シリアル番号
|
||||
lbl.row.seal,封印シール
|
||||
lbl.bracket.0,良好
|
||||
lbl.bracket.1,キズあり
|
||||
lbl.serial.0,正常
|
||||
lbl.serial.1,工場コードまたは桁数異常
|
||||
lbl.serial.2,型番コード不一致
|
||||
lbl.seal.0,無傷
|
||||
lbl.seal.2,欠損
|
||||
item.guide.name,グラフィックボード鑑定ガイド
|
||||
item.guide.desc,グラフィックボードの偽造品を見分け、価値を判定するためのガイド。
|
||||
lbl.row.spec,型番
|
||||
news.prehalving.title,PSC半減期が接近
|
||||
news.prehalving.desc,3日後、採掘人が毎晩獲得できるコインが半減する。保有者は価格上昇を期待している。
|
||||
tab.home,ホーム
|
||||
tab.bank,銀行
|
||||
tab.poinbase,Poinbase
|
||||
tab.web3,Web3
|
||||
home.enter,入る
|
||||
home.open,開く
|
||||
home.summary,クレジット {0} | オンチェーン資産 約{1}クレジット
|
||||
home.lastnight,{0}日目の夜:{1} PSC採掘、リグ稼働 {2}/{3}台
|
||||
entry.bank,銀行
|
||||
entry.bank.l1,入出金、家賃
|
||||
entry.bank.l2,クレジット {0}
|
||||
entry.poinbase,Poinbase
|
||||
entry.poinbase.l1,規制準拠取引所
|
||||
entry.poinbase.l2,PSC {0}クレジット
|
||||
entry.web3,Web3
|
||||
entry.web3.l2,約{0}クレジット
|
||||
entry.help,ヘルプ
|
||||
entry.help.l1,Web3ハンドブック
|
||||
bank.cash,クレジット:{0}
|
||||
bank.rent,家賃:{0}クレジット、期日:{1}日後
|
||||
bank.crc,Poinbase口座(CRC):{0}
|
||||
poin.account,Poinbase口座:CRC {0}、PSC {1}
|
||||
avg.line,{0}の平均購入単価:{1}クレジット
|
||||
avg.short,平均単価 {0}
|
||||
avg.none,—
|
||||
col.asset,資産
|
||||
col.amount,数量
|
||||
col.value,評価額
|
||||
col.avg,平均単価
|
||||
bank.cash.k,クレジット
|
||||
bank.rent.k,家賃
|
||||
bank.rent.v,{0}、期日:{1}日後
|
||||
bank.crc.k,Poinbase口座(CRC)
|
||||
poin.account.h,Poinbase口座
|
||||
trade.h,取引
|
||||
web3.wallet.h,オンチェーンウォレット
|
||||
stable.ok,ペグ正常
|
||||
stable.depeg,デペグ
|
||||
stable.warn,警告:ステーキング準備率低下
|
||||
stable.spiral,崩壊中
|
||||
aml.taint,アカウント汚染率:{0}%
|
||||
mixer.h,ミキサー
|
||||
mixer.ok,状態:正常稼働
|
||||
mixer.sanctioned,状態:制裁中(残り{0}日)。この間に出金されたコインはフラグ付きとなる。
|
||||
mixer.pending,入金処理中
|
||||
mixer.none,処理中の入金はありません。
|
||||
mixer.col.taint,汚染
|
||||
mixer.col.ready,完了
|
||||
mixer.day,{0}日目
|
||||
mixer.deposit,入金
|
||||
mixer.balance,残高:{1} {0}
|
||||
mixer.rounds,ラウンド数
|
||||
mixer.preview,{0} {1} の受取見込み、汚染は約 {2}% 低下、{3}日目に完了。
|
||||
mixer.go,ミキサーに入金
|
||||
mixer.min,入金には最低{0}クレジット相当が必要です。
|
||||
mixer.done,{0} {1} を入金。{2}日目に受取可能。
|
||||
mixer.upgrade.title,ミキサー
|
||||
mixer.upgrade.desc,ターミナルのグレーネットページにあるミキサーをアンロック:汚染コインを入金し、数日後に汚染を減らして回収する。ミックス直後のコインは出金審査がより厳格化される。取締期間中はミキサーが制裁対象となる可能性があり、その間に出金されたコインはフラグ付きとなる。
|
||||
news.sanction.title,ミキサーを制裁リストに追加
|
||||
news.sanction.desc,警察が複数のミキシングサービスに制裁を実施。今後数日間にミキサーから出金された資金は不審として扱われる。
|
||||
nightlog.mixer,ミキサーから {0} {1} を回収。汚染 {2} → {3}。
|
||||
nightlog.mixer_flag,(制裁期間中に出金。アドレスはフラグ付き)
|
||||
nightlog.mixer_rug,ミキサーの運営者が持ち逃げした:{0} {1} は戻ってこなかった。
|
||||
web3.sub.trade,取引
|
||||
gray.sub.mixer,ミキサー
|
||||
msg.frozen,コインは凍結中のため、解除されるまで使用できません。
|
||||
wallet.frozen,{0}:{1} 凍結中、{2}日目に解除
|
||||
nightlog.crt_freeze,取締期間中に闇市場がアドレスリストを引き渡した:{0} CRT が{1}日目まで凍結された。
|
||||
nightlog.thaw,{0} {1} の凍結が解除された。
|
||||
news.crtfreeze.title,闇市場、取締に伴い一部のCRTアドレスを凍結
|
||||
news.crtfreeze.desc,噂によれば、闇市場は見逃してもらう見返りに、警察へCRTアドレスのリストを渡したとのことだ。評判が低い保有者ほど凍結される可能性が高い。
|
||||
black.upgrade.title,Web3ショップ
|
||||
black.upgrade.desc,ターミナルのグレーネットページのショップをアンロック:闇市場派閥のオンチェーン拠点。禁制品が毎週入荷し、時にはハイテク品やグラフィックボード(割増価格)も並ぶ。現物を購入するか、注文して配達人を待つ。決済はコイン限定(PSC、CRT、CRA、Ponero)、汚染コインも受付。闇市場の評判が必要で、取締期間中はオフラインとなる。
|
||||
black.offline,取締期間中、ショップのオンチェーン入口はオフラインとなる。
|
||||
black.closed,ショップに入るには闇市場の評判が {0} 必要(現在:{1})。
|
||||
black.sub.buy,購入
|
||||
black.shop.h,現物カウンター
|
||||
black.rep,闇市場の評判 {0}
|
||||
black.empty,今週の商品は完売。
|
||||
black.offer,{0} ×{1} {2}クレジット相当
|
||||
black.buy,購入
|
||||
black.bought,取引完了:{0}は保管庫に保管された。
|
||||
black.pay.h,支払い
|
||||
black.desk.h,Ponero窓口
|
||||
black.desk.left,本日の残額:{0}(上限 {1})
|
||||
black.desk.price,Ponero価格:{0}
|
||||
black.desk.swap,スワップ
|
||||
black.desk.in,Poneroへスワップ
|
||||
black.desk.out,Poneroからスワップ
|
||||
black.desk.go,スワップ
|
||||
black.desk.fail,スワップ失敗:残高不足、限度額超過、または数量が無効です。
|
||||
black.sub.orders,注文
|
||||
black.rugged,プラットフォームがダウンした。再開まであと{0}日。
|
||||
black.seller,取引数 {1}、高評価 {2}%
|
||||
black.orders.h,注文カタログ
|
||||
black.order,注文
|
||||
black.mode.Escrow,エスクロー
|
||||
black.mode.Advance,事前リリース
|
||||
black.ordered,注文完了:{0}、{1}日目に到着予定。
|
||||
black.mine.h,注文一覧
|
||||
black.mine.none,注文はまだありません。
|
||||
black.mine.line,{0}({1}、{2}):{3}、{4}日目
|
||||
black.state.Pending,輸送中
|
||||
black.state.Ready,到着済み
|
||||
black.state.Done,受取済み
|
||||
black.state.Refunded.scam,売り手逃亡、返金済み
|
||||
black.state.Lost.scam,売り手逃亡、資金消失
|
||||
black.state.Lost.rug,プラットフォームがラグプル、資金消失
|
||||
black.state.Lost.intercept,途中で押収
|
||||
black.forum.h,フォーラム情報
|
||||
black.forum.quiet,最近は静かだ。
|
||||
black.forum.scam,{0} は金を受け取っても発送しないらしい。
|
||||
black.forum.rug,最近出金が遅延しており、サイトはプロモーション中、苦情スレッドも大量に削除されている。
|
||||
nightlog.bm.scam_refund,闇市場:売り手 {0} が逃亡。{1} のエスクロー資金が返金された。
|
||||
nightlog.bm.scam_loss,闇市場:売り手 {0} が事前リリースの資金を持ち逃げした。{1} を失った({2}クレジット相当)。
|
||||
nightlog.bm.intercept,闇市場:{0} の荷物が押収された。支払い済みの{1}クレジット相当を失った。
|
||||
nightlog.bm.rug,闇市場:プラットフォームがラグプルした。{0} の輸送中資金({1})を失った。
|
||||
nightlog.bm.reopen,闇市場:何者かが元の場所で営業を再開した。
|
||||
news.bmrug.title,闇市場プラットフォームがラグプル
|
||||
news.bmrug.desc,闇市場のオンチェーン入口が一夜にして閉鎖され、すべてのエスクローおよび事前リリースの資金が消滅した。数日後には新しい入口が現れる見込みだ。
|
||||
courier.name,配達人
|
||||
courier.line1.1,荷物が届いたぞ。
|
||||
courier.line1.2,あんた宛ての荷物だ。
|
||||
courier.line2.1,中身は言うなよ。知りたくもない。
|
||||
courier.line2.2,ここに置いたぞ。じゃあな。
|
||||
gray.sub.black,ショップ
|
||||
black.stock,残り {0}
|
||||
black.price,{0}クレジット相当
|
||||
black.noadvance,事前リリース不可
|
||||
black.kind.gpu,グラフィックボード 状態 {0}%
|
||||
black.kind.Contraband.1,禁制品(低)
|
||||
black.kind.Contraband.2,禁制品(中)
|
||||
black.kind.Contraband.3,禁制品(高)
|
||||
black.kind.Tech,ハイテク品(割増)
|
||||
nightlog.bm.ready,闇市場:{0} が到着。開店後に配達人が届けてくれる。
|
||||
guide.web3.title,Web3ハンドブック
|
||||
guide.web3.text,銀行と取引:銀行ページは閲覧専用で、現金、家賃、Poinbase口座のCRCを表示する。入金と出金はPoinbaseの資金ページで行い、先にコインを選ぶ。CRCは銀行口座とウォレットのどちらでも可能で、他のコインはウォレットのみ。銀行からの入金はクレジットをPoinbase口座のCRCに変換し、銀行への出金はCRCをクレジットに戻すが、Poinbase口座の汚染を対象としたコンプライアンス審査が行われる。ウォレットへの出金は受取アドレスの入力が必要で、数回の承認を経て着金する。ガス代は通常の段階で固定され、送るコインから差し引かれる。アドレスの形式やチェックディジットが誤っていると拒否される。形式が正しくても誰も使っていないアドレスに送ったコインは失われる。¶取引:PSCは Probably Stolen Coin の略称で、グラフィックボードや専用採掘機で採掘されるコイン。Poinbaseの現物にはPSC/CRCとSPARK/CRCの2つのペアがあり、チャートで選んだコインに合わせて切り替わる。買いも売りも取引対象のコインの数量で入力する。プレビューには支払う・受け取る決済通貨が表示され、平均価格は手数料込み、スリッページは手数料を含まない。¶Web3の取引ページでは任意の2種類のコインを交換でき、必ずCRCを経由する。CRCが片側なら1つのプール、そうでなければ2つのプールを通り、手数料は2回、スリッページは重なる。プレビューに受取数量、経由するプール数、損失が表示される。ステーブルコイン同士(CRT・CRAとCRC)はステーブルプールを使い、手数料は{StableFee:%}、ペッグ付近ではスリッページがほぼない。ペッグが外れると流動性が薄くなり、崩壊時には流動性が引き揚げられてスリッページが急増する。§ハードウェアウォレット:チェーン上のコインはPLEDGERハードウェアウォレットに保管され、ウォレットごとに残高と汚染が個別に管理される。ウォレットはアイテムで、取引ターミナルにドラッグして読み込む。ターミナルのウォレットページで開き、ターミナル右上で接続・切断する。Web3ページの取引とグレーネットページのショップ、ミキサーは接続されたウォレットを使用する。ウォレットがない、または接続していないときは閲覧のみで、残高はすべて0になる。コイン決済の客は接続されたウォレットに支払う。¶支払い(ショップ、ミキサー、Ponero窓口、出品手数料)はまずターミナルで請求書を発行し、ウォレット側で送金先アドレスを入力して✓を長押しして署名する。アドレスの末尾2文字はチェックサムのため、1文字の誤入力なら通常は検出されるが、偶然有効なアドレスに一致した場合は誰も使っていないアドレスにコインが送られてしまう。DEXでのスワップもウォレットでの署名が必要となる。¶Poinbaseはカストディ口座で、入金はウォレットからPoinbaseの入金アドレスへ送金し(受け付けるのはPSC、CRC、SPARKのみ。規制下の取引所なので闇市場のCRTと革命軍のCRAは受け付けず、入金アドレスへの送金はウォレットが止める)、出金はPoinbaseの資金ページで行う。ウォレットページのエクスプローラーではアドレスで送金履歴を検索でき、実際に行われた送金のみが表示される:自分のウォレットのすべての入出金(送金、DEXスワップなどのコントラクト呼び出し、採掘機の収益、出金、他人から送られたコイン)。Poneroはプライバシーコインのため表示されない。追加のハードウェアウォレットはジャックソン博士から購入し、取引ターミナルにドラッグして追加する(最大{WalletMax}個)。ショップにはより安価なものもある。不要になったウォレットは、ウォレットページで破棄できる。中のコインは永久に失われ、その後このアドレスに送られたものも失われる。¶送金にはガス代が必要で、低速・通常・高速の3段階があり、ガス価格は約1週間周期で上下する。ネットワーク混雑時はガス代が高騰し、低速のトランザクションはメムプールから除外されることがある。送金前にアドレス全体を必ず確認すること。§ステーキング:革命家のプールにCRAをステーキングすると日利が付与され、利息は元本に複利で組み入れられる。出金するにはまず申請しLine truncated
|
||||
courier.odd1,……荷物が届いた。
|
||||
courier.odd2,(ポケットに手を入れたままだ)ここにサインを。
|
||||
courier.sign,サイン
|
||||
courier.refuse,受取拒否
|
||||
courier.signed,よし。動くな、警察だ。
|
||||
courier.refused,……そうか、ならいい。
|
||||
black.state.Lost.seized,押収
|
||||
black.state.Lost.refused,受取拒否
|
||||
black.forum.easy,最近順調すぎる。売り手の発送はいつもより早く、見慣れない新規アカウントも増えている。
|
||||
black.forum.busted,{0} が逮捕されたらしいが、注文履歴は残ったままだ。
|
||||
nightlog.bm.trap.honeypot,闇市場:プラットフォームが警察に接収された。購入した {0} が追跡され、犯罪証拠 {1} が記録された。
|
||||
nightlog.bm.trap.seller,闇市場:売り手が逮捕され、残された注文履歴から関与が特定された:{0}、犯罪証拠 {1} が記録された。
|
||||
tab.mining,マイニング
|
||||
courier.sign.say,サインする。
|
||||
courier.refuse.say,受け取らない。送り返せ。
|
||||
black.forum.busted_buyer,買い手がまとめて逮捕されたらしいが、取引記録はプラットフォームに残ったままだ。
|
||||
nightlog.bm.sale_sold,闇市場:出品した {0} が売却された。代金 {1}、{2}日目に入金予定。
|
||||
nightlog.bm.sale_paid,闇市場:{0} の売上代金 {1} が着金した(CRT)、うち汚染 {2}。
|
||||
nightlog.bm.sale_fake,闇市場:買い手に {0} が偽物だと見破られて返品された。評価が低下した。
|
||||
nightlog.bm.sale_rug,闇市場:プラットフォームがラグプルを起こした。{0} と売上代金({1})が消失した。
|
||||
black.sub.sell,出品
|
||||
black.sell.h,出品
|
||||
black.sell.mult,価格倍率
|
||||
black.sell.none,保管庫に出品可能なアイテムがありません。
|
||||
black.sell.rating,高評価 {0}%
|
||||
black.mine.sale,{0} 参考 {1} 価格 {2}(×{3}):{4}
|
||||
black.sale.Listed,出品中
|
||||
black.sale.Paid,入金済
|
||||
black.sale.Lost,ラグプルにより消失
|
||||
black.sale.Delisted,出品取消済
|
||||
black.sale.Delisted.fake,買い手に偽物と見破られ返品
|
||||
black.kind.gpunew,グラフィックボード 新品
|
||||
merchant.GpuNew,新品グラフィックボード
|
||||
merchant.GpuUsed,中古グラフィックボード
|
||||
merchant.Arms,武器
|
||||
merchant.Docs,キーカード・チップ
|
||||
merchant.Pharma,医薬品
|
||||
merchant.Bulk,大口商品
|
||||
black.days,{0}日で到着
|
||||
black.sell.listedall,{0}件を出品しました。
|
||||
merchant.Rigs,マイニングリグ・電源
|
||||
merchant.Modules,モジュール
|
||||
merchant.GunMods,ガンスミスパーツ
|
||||
merchant.Chem,化学品
|
||||
merchant.Brewer,醸造
|
||||
merchant.Farm,水耕栽培
|
||||
merchant.Husbandry,畜産
|
||||
merchant.Miner,採掘用品
|
||||
merchant.Water,水
|
||||
merchant.Storage,倉庫
|
||||
merchant.Tools,工具
|
||||
merchant.Luxury,高級品
|
||||
black.kind.Goods,商品
|
||||
merchant.Elite,エリートショップ
|
||||
merchant.Personal,個人売り手
|
||||
black.pay.confirm,請求書
|
||||
black.pay.to,送金先アドレス:{0}
|
||||
black.pay.cancel,破棄
|
||||
pay.mix,ミキサー {0} {1}
|
||||
pay.swap,Ponero窓口 {0} {1}
|
||||
black.edit.cancel,キャンセル
|
||||
merchant.Platform,プラットフォーム
|
||||
black.platform.line,プラットフォーム現物 即時配達
|
||||
black.orders.in,購入
|
||||
black.orders.out,売却
|
||||
black.desk.pair,PONERO [プライバシーコイン] 価格 {0}
|
||||
black.pay.amount,数量:{0} {1}(約{2}クレジット)
|
||||
black.pay.wallet,ウォレットから送金
|
||||
hw.total,合計 ≈ {0}クレジット
|
||||
hw.pending.bill,未払い:{0}
|
||||
hw.pending.sign,署名待ち:{0}
|
||||
hw.send,送金
|
||||
hw.review,署名リクエスト
|
||||
hw.to,送金先アドレス
|
||||
hw.avail,利用可能 {1} {0}
|
||||
hw.amount,数量
|
||||
hw.bill,請求書:{0} {1} {2}
|
||||
hw.fill,請求額を入力
|
||||
hw.next,✓ 次へ × 戻る
|
||||
hw.err.format,無効なアドレス形式です。
|
||||
hw.err.checksum,アドレスのチェックサム検証に失敗しました。
|
||||
hw.err.self,このウォレット自身のアドレスには送金できません。
|
||||
hw.err.asset,請求書の指定トークンは {0} です。
|
||||
hw.err.short,請求額を下回っています:{0} {1}。
|
||||
hw.err.nobill,この送金先の未払い請求書はありません。
|
||||
hw.review.h,確認
|
||||
hw.contract,コントラクト呼出
|
||||
hw.review.to,送金先アドレス
|
||||
hw.review.amount,{0} {1}(約{2}クレジット)
|
||||
hw.review.bill,請求書:{0}
|
||||
hw.review.unknown,このアドレスの取引履歴はありません。
|
||||
hw.review.over,{0} {1} の過払いが発生します。超過分は返金されません。
|
||||
hw.hold,✓ 長押しで署名 × 拒否
|
||||
hw.tx.h,トランザクション
|
||||
hw.tx.signing,署名中…
|
||||
hw.tx.mempool,ブロードキャスト完了。メムプールで待機中…
|
||||
hw.tx.packed,ブロック #{0} に取り込まれました
|
||||
hw.tx.confirm,ブロック #{0} 確認 {1}/{2}
|
||||
hw.skip,スキップ
|
||||
hw.done.h,確認済み
|
||||
hw.done.block,ブロック #{0}
|
||||
hw.done.sent,{0} {1} → {2}
|
||||
hw.done.void,このアドレスは使われていません。コインは失われました。
|
||||
hw.back,戻る
|
||||
hw.rejected,ウォレット側で署名が拒否されました。
|
||||
hw.wait,ウォレットで確認してください。
|
||||
hw.swap,スワップ {0} {1} → 約 {2} {3}
|
||||
tab.wallets,ウォレット
|
||||
hw.wallet.n,ウォレット {0}
|
||||
hw.review.own,自身のウォレット:{0}
|
||||
hw.review.poinbase,Poinbase入金アドレス
|
||||
poin.deposit,入金アドレス:{0}
|
||||
wallets.count,ウォレット {0}/{1}
|
||||
wallets.col.name,名前
|
||||
wallets.col.addr,アドレス
|
||||
wallets.col.taint,汚染
|
||||
wallets.open,開く
|
||||
wallets.use,接続
|
||||
wallets.current,接続中
|
||||
wallets.added,{0} を追加しました:{1}
|
||||
nightlog.drained,{0} 内のコインが不正に送金された(約{1}クレジット相当)。
|
||||
item.hwwallet.name,PLEDGER ハードウェアウォレット
|
||||
item.hwwallet.desc,大画面のハードウェアウォレット。取引ターミナルにドラッグしてウォレットを追加する(最大5つ)。
|
||||
poin.empty,アカウントに残高がありません。
|
||||
hw.copy,コピー
|
||||
hw.paste,貼り付け
|
||||
hw.copied,アドレスをコピーしました。
|
||||
hw.copied.addr,{0} をコピーしました
|
||||
hw.balance.frozen,(凍結 {0})
|
||||
wallets.destroy,破棄
|
||||
wallets.destroy.sure,破棄の確認
|
||||
wallets.destroyed,{0} を破棄しました:{1}
|
||||
wallets.destroy.warn,{0}を破棄すると中のコインは永久に失われる。もう一度押して確定する。
|
||||
payout.label,受取先
|
||||
payout.unset,未設定
|
||||
payout.set,アドレスを設定
|
||||
payout.h,受取アドレス
|
||||
payout.cur,現在:{0}
|
||||
payout.pick,自分のウォレット:
|
||||
payout.manual,またはアドレスを入力:
|
||||
payout.clear,クリア
|
||||
payout.err,無効なアドレスです。
|
||||
nightlog.mined.lost,採掘した{0} PSCが失われた:受取アドレス未設定、またはそのウォレットが破棄済み。
|
||||
wallets.none,ウォレットが読み込まれていません。ハードウェアウォレットをターミナルにドラッグしてください。
|
||||
web3.err.noconn,ウォレットが接続されていません。
|
||||
web3.connect,ウォレットを接続
|
||||
web3.disconnect,切断
|
||||
web3.conn,{0} {1}
|
||||
hw.balance.value,≈ {0}
|
||||
wallets.rename,名前の変更
|
||||
wallets.rename.h,{0} の新しい名前
|
||||
wallets.rename.ok,OK
|
||||
hw.fee.slow,低速
|
||||
hw.fee.normal,標準
|
||||
hw.fee.fast,高速
|
||||
hw.fee,ガス代 {0} {1}(約{2}クレジット)
|
||||
hw.confs,必要な承認数:{0}
|
||||
hw.congested,ネットワーク混雑
|
||||
hw.congested.slow,ネットワーク混雑:低速手数料はメムプールから除外される可能性があります
|
||||
hw.recent,最近
|
||||
hw.recent.out,→ {0} {1} {2}
|
||||
hw.recent.in,← {0} {1} {2}
|
||||
hw.review.history,過去の取引履歴あり
|
||||
hw.tx.stuck,メムプールで待機中…
|
||||
hw.tx.dropped,メムプールから除外されました。送金は行われませんでしたが、ガス代は消費されました。
|
||||
hw.dropped.h,未完了
|
||||
hw.err.fee,ガス代を支払う残高が不足しています。
|
||||
news.congest.title,チェーン混雑
|
||||
news.congest.desc,エアドロップの駆け込み需要でチェーンが混雑している。ガス代は何倍にも跳ね上がり、低ガス代のトランザクションはメムプールから除外される可能性がある。
|
||||
news.phish.title,Poinbaseからのお知らせ:入金アドレス移行
|
||||
news.phish.desc,Poinbaseはウォレットシステムをアップグレードしました。旧入金アドレスは廃止されます。新しいアドレス {0} に資産を送金してください。
|
||||
black.forum.phish,ミキサーの新アドレスが投稿された:{0}。旧アドレスは監視されているとのことだ。
|
||||
hw.gas,ガス ×{0}
|
||||
web3.sub.stake,ステーキング
|
||||
stake.h,革命家のステーキングプール
|
||||
stake.rate,日利 {0}%、出金待機期間は{1}日(待機中は利息なし)
|
||||
stake.low,準備率低下、日利引き下げ
|
||||
stake.cra,CRA価格 {0} {1}
|
||||
stake.none,ステーキング中の資産はありません。
|
||||
stake.col.wallet,ウォレット
|
||||
stake.col.amount,ステーキング額
|
||||
stake.col.queue,ロック解除中
|
||||
stake.day,({0}日目)
|
||||
spark.price,バランストークン SPARK {0}クレジット
|
||||
stake.ops,{0}
|
||||
stake.avail,CRA {0} ステーキング中 {1}
|
||||
stake.do,ステーキング
|
||||
stake.undo,出金申請
|
||||
stake.sum.in,{0} CRA をステーキング
|
||||
stake.sum.out,{0} CRA の出金申請({1}日後に着金)
|
||||
stake.done.in,{0} CRA をステーキングしました。
|
||||
stake.done.out,{0} CRA の出金を申請しました。{1}日目にウォレットに戻ります。
|
||||
nightlog.stakeint,ステーキング利息 +{0} CRA。
|
||||
nightlog.unstaked,ステーキングから出金された {0} CRA が {1} に戻った。
|
||||
news.crawarn.title,革命家のステーキングプールに不穏な動き
|
||||
news.cralow.title,革命家がステーキングの日利を引き下げ
|
||||
stake.avail2,SPARK {0}
|
||||
poin.sub.spot,現物
|
||||
poin.sub.perp,無期限先物
|
||||
perp.h,無期限先物
|
||||
perp.acct,証拠金口座 CRC {0}
|
||||
perp.debt,負債 {0}。{1}日後にアイテムが差し押さえられます。完済するまで新規建ておよび出金はできません。
|
||||
perp.banned,無期限先物口座は利用停止中です(残り{0}日)。
|
||||
perp.none,保有ポジションはありません。
|
||||
perp.col.pos,ポジション
|
||||
perp.col.notional,想定元本
|
||||
perp.col.price,建値 → 現在値
|
||||
perp.col.pnl,損益
|
||||
perp.col.liq,ロスカット価格
|
||||
perp.long,ロング
|
||||
perp.short,ショート
|
||||
perp.rate,{0} 価格 {1} 資金調達料 {2}%/夜
|
||||
perp.fund,保険基金 {0}
|
||||
perp.open,新規建て
|
||||
perp.margin,証拠金額(CRC)
|
||||
perp.do.open,新規建て
|
||||
perp.do.add,証拠金追加
|
||||
perp.do.close,決済
|
||||
perp.opened,{0} {1} を新規建てしました:証拠金 {2} CRC、{3}×。
|
||||
perp.added,{0} CRC の証拠金を追加しました。
|
||||
perp.closed,決済完了。{0} CRC が口座に戻りました(損益 {1})。
|
||||
perp.deficit,口座残高が不足し、不足分 {0} は保険基金および負債により補填されました。
|
||||
perp.err.Banned,無期限先物口座は利用停止中です。
|
||||
perp.err.Debt,未払いの負債があるため、新規ポジションを建てられません。
|
||||
perp.err.Leverage,レバレッジがこの商品の設定上限を超えています。
|
||||
perp.err.Size,この商品の保有ポジション上限を超えています。
|
||||
perp.err.Funds,口座のCRC残高が不足しています(手数料を含む)。
|
||||
perp.err.Opposite,同一商品でロングとショートを同時に保有することはできません。先に決済してください。
|
||||
perp.err.NoPosition,ポジションがありません。
|
||||
perp.err.Margin,証拠金額を入力してください。
|
||||
perp.debt.block,無期限先物の未払い負債があるため、出金できません。
|
||||
nightlog.perp.liq,{0}がロスカットされた。証拠金{1}を失った。
|
||||
nightlog.perp.adl,保険基金が枯渇し、{0}が自動減倉され利益{1}が差し引かれた。
|
||||
nightlog.perp.interest,無期限先物の負債に利息が発生。現在の負債総額は{0}。
|
||||
nightlog.perp.seize,無期限先物の負債が延滞。押収品から{0}が充当された。
|
||||
nightlog.perp.writeoff," {0}が貸倒処理された。無期限先物口座は{1}日間利用停止。"
|
||||
perp.slip.title,無期限先物負債差押通知
|
||||
perp.preview2,手数料 {0} ロスカット {1}
|
||||
nightlog.perp.repaid,無期限先物の赤字:返済のためPoinbase口座から{0} CRCが引き落とされた。
|
||||
perp.err.Thin,この注文のスリッページが大きすぎるため即座にロスカットされます。注文規模またはレバレッジを下げてください。
|
||||
perp.err.Single,ポジションは同時に1つまで。証拠金を追加してください。
|
||||
mat.hypertech_electronic,ハイパーテック電子部品
|
||||
item.asic.name,RatDigg {0} 専用採掘機
|
||||
item.asic.dead.name,焼損したRatDigg {0} 専用採掘機
|
||||
item.asic.desc,定格 {0} GH/s。定格消費電力 {1} kJ/日。状態 {2}。独立型専用採掘機:稼働にはバッテリーが必要、モジュール装着可能。
|
||||
item.asic.dead.desc,焼損状態。電子部品をドラッグして修理:現在は{0} × {1}が必要。修理後は耐久度が20低下する。
|
||||
item.asic.dead.fixed,修理済み。
|
||||
merchant.Asic,専用採掘機の取引人
|
||||
black.kind.asic,専用採掘機 状態{0}%
|
||||
black.kind.asicnew,専用採掘機 新品
|
||||
news.erawarn.title,RatDiggが新世代の専用採掘機を間もなく発表
|
||||
news.erawarn.desc,専用採掘機メーカーが新機材を発表し、業界内では大手ファームが一斉に機材を刷新すると予測されている。グラフィックボードによるマイニングの黄金期も終わりが近いとの声もある。
|
||||
news.era.title,専用採掘機時代
|
||||
news.era.desc,新世代の専用採掘機が量産体制に入り、大手ファームの電力コストは半減した。ネットワーク全体のハッシュレートは上昇し、グラフィックボードによる採掘の利益は希薄化する。
|
||||
web3.sub.predict,予測
|
||||
predict.h,予測市場
|
||||
predict.acct,{0}:CRC {1}
|
||||
predict.none,本日開催中の市場はありません。
|
||||
predict.closed,受付終了
|
||||
predict.row,はい {0} いいえ {1}
|
||||
predict.held,保有: {0} ×{1}、コスト {2}
|
||||
predict.yes,はい
|
||||
predict.no,いいえ
|
||||
predict.void,無効
|
||||
predict.result,{0}日目 {1} 結果:{2} {3}
|
||||
predict.pick,取引
|
||||
predict.price,1口あたりの価格:はい {0} いいえ {1}
|
||||
predict.pos,{0}:{1} ×{2}
|
||||
predict.pos2,コスト {0} 払戻 {1}
|
||||
predict.sum.buy,{2} CRCで「{1}」を購入:{0}
|
||||
predict.sum.sell,予測ポジションを売却:{0}
|
||||
predict.closed.note,受付終了、決済待ち。
|
||||
predict.preview,「{0}」を購入: 約{1}口(平均{2})、的中時の純益 {3}
|
||||
predict.buy.yes,「はい」を購入
|
||||
predict.buy.no,「いいえ」を購入
|
||||
predict.sell,すべて売却
|
||||
predict.bought,{2}で「{0}」を購入。的中時の払戻金は{1}。
|
||||
predict.sold,売却完了、{0}を受け取った。
|
||||
predict.err.Closed,この市場はすでに受付を終了しています。
|
||||
predict.err.Amount,数量が無効です。
|
||||
predict.err.Funds,ウォレット内のCRCが不足しています。
|
||||
predict.err.Cap,この市場の保有上限を超えています。
|
||||
predict.err.Opposite,反対側のポジションを保有しています。先に売却してください。
|
||||
predict.err.NoPosition,この市場のポジションがありません。
|
||||
predict.win.one,{0}日目
|
||||
predict.win.range,{0}〜{1}日目
|
||||
predict.q.event,{0}:「{1}」が発生
|
||||
predict.q.faction,{0}:{1}が作戦を開始
|
||||
predict.q.purity,{0}:{1}の純度 ≥ {2}
|
||||
predict.q.price,{0}:{1}の価格 ≥ {2}
|
||||
predict.faction.FACTION_SECURITY,警察
|
||||
predict.faction.FACTION_REVOLUTION,革命家
|
||||
predict.faction.FACTION_LOWER_LEVEL,下層
|
||||
predict.faction.FACTION_UPPER_LEVEL,上層
|
||||
predict.faction.FACTION_BLACK_MARKET,闇市場
|
||||
predict.purity.gutter,下層水
|
||||
predict.purity.rust,上層水
|
||||
nightlog.predict.win,予測的中:「{0}」、{1}が払い戻された。
|
||||
nightlog.predict.lose,予測不的中:「{0}」、賭け金{1}を失った。
|
||||
nightlog.predict.void,予測無効:「{0}」、賭け金{1}が返還された。
|
||||
nightlog.predict.caught,インサイダー取引が摘発:「{0}」、賭け金と配当{1}が没収され、詐欺の犯罪証拠が記録された。
|
||||
predict.tab.markets,市場
|
||||
predict.tab.intel,情報
|
||||
predict.acct.crt,{0}:CRT {1}
|
||||
predict.tier.0,低
|
||||
predict.tier.1,中
|
||||
predict.tier.2,高
|
||||
predict.clue.tip,情報({0}):「{1}」
|
||||
predict.clue.queued,予定:{0}日目に開始
|
||||
predict.clue.queued2,予定:{0}日目「{1}」
|
||||
predict.clue.cool,イベント進行中またはクールダウン中
|
||||
predict.clue.busy,派閥作戦が進行中。当面の間、新たな作戦はなし
|
||||
predict.clue.halving,半減期は{0}日目。その1週間前から価格アンカーが上昇
|
||||
predict.clue.anchor,現在の価格アンカー: {0}
|
||||
predict.clue.gas,直近のガス:{0}
|
||||
predict.clue.drain,1夜あたりの消費: {0}
|
||||
predict.clue.era,{0}〜{1}日目の間でランダム、事前予告あり
|
||||
predict.clue.era.warned,予告発令済み:{0}〜{1}日目に開始
|
||||
predict.q.gas,{0}:ガス指数 ≥ {1}
|
||||
predict.q.cra,{0}:CRA警告が発令
|
||||
predict.q.era,{0}:専用採掘機時代が開始
|
||||
predict.era,専用採掘機時代
|
||||
predict.pos3,平均 {0} 現在 {1}
|
||||
predict.pos4,今売却すると{0}を獲得
|
||||
intel.h,情報ブローカー
|
||||
intel.locked,Web3ショップと闇市場の評判{0}が必要。
|
||||
intel.brief.buy,情勢ブリーフィングを購入({0} CRT)
|
||||
intel.brief.none,ブリーフィングは未購入。
|
||||
intel.brief.day,{0}日目のブリーフィング
|
||||
intel.tips.h,内部情報
|
||||
intel.tips.none,照会可能な項目なし(派閥作戦および専用採掘機時代のみ)。
|
||||
intel.tip.buy,精度約{0}% {1} CRT
|
||||
intel.err.funds,ウォレットのCRTが不足しているか、対象の市場が購入不可です。
|
||||
intel.brief.sum,情勢ブリーフィング、{0} CRT
|
||||
intel.tip.sum,内部情報 {0} CRT:{1}
|
||||
intel.brief.done,情勢ブリーフィングを入手した。
|
||||
intel.tip.done,情報内容:「{0}」
|
||||
predict.brief.levels,警察 {0} 革命家 {1} 闇市場 {2} 動乱 {3} 上層 {4}
|
||||
predict.brief.busy,{0}:作戦進行中
|
||||
predict.brief.queued,{0}:作戦予定あり
|
||||
predict.brief.none,{0}:発動可能な作戦なし
|
||||
predict.brief.can,{0}:{1}を発動可能
|
||||
predict.clue.push,プレイヤーの価格誘導 {0}%: 操縦リスク高
|
||||
nightlog.predict.manip,予測が価格操縦と認定:「{0}」、賭け金{1}が没収され、詐欺の犯罪証拠が記録された。
|
||||
news.manip.title,取引所が不審な取引を調査
|
||||
news.manip.desc,規制当局の発表によると、大口現物注文で価格を操作し、デリバティブや予測市場で不当な利益を得た者がおり、関係資金は差し押さえられた。
|
||||
perp.manip,決済利益{0}が価格操縦と認定され没収。無期限先物口座が{1}日間凍結された。
|
||||
web3.sub.ponzi,利回り
|
||||
ponzi.h,ポンジ・スキーム
|
||||
ponzi.acct,発行者ウォレット {0}:CRC {1}
|
||||
ponzi.rate,日利 {0}%
|
||||
ponzi.pool,プール {0} / 上限 {1}
|
||||
ponzi.inflow,昨晩の新規入金 {0}
|
||||
ponzi.interest,今晩の支払利息 {0}
|
||||
ponzi.own,自己負担利息合計 {0}
|
||||
ponzi.wind,通報リスク:{0}
|
||||
ponzi.wind.low,低
|
||||
ponzi.wind.mid,中
|
||||
ponzi.wind.high,高
|
||||
ponzi.idle,ポンジ・スキームは未発行。
|
||||
ponzi.done,ポンジ・スキームは終了しました。1セーブデータにつき1回のみ発行可能。
|
||||
ponzi.ops,操作
|
||||
ponzi.rug,プールをラグプル({0})
|
||||
ponzi.rug.confirm,再クリックで{0}のラグプルを確定
|
||||
ponzi.rugged,{0}を持ち逃げした。全額が汚染資金。
|
||||
ponzi.open,ポンジ・スキームを発行
|
||||
ponzi.ad,宣伝費{0} CRCが現在のウォレットから支払われます。署名が必要です。
|
||||
ponzi.start,発行
|
||||
ponzi.started,ポンジ・スキームを発行した。
|
||||
ponzi.err,ウォレットのCRCが不足しており、宣伝費を支払えません。
|
||||
nightlog.ponzi.collapse,利息を支払えず取り付け騒ぎが発生。プール{0}が没収され、詐欺の犯罪証拠が記録され、下層の評判がリセットされた。
|
||||
nightlog.ponzi.reported,通報されたためプール{0}が没収され、詐欺の犯罪証拠が記録され、下層の評判がリセットされた。
|
||||
news.ponzi.title,ポンジ・スキームが破綻
|
||||
news.ponzi.desc,下層で運営されていたポンジ・スキームが通報された。投資家が殺到し、当局によって資金が凍結された。
|
||||
news.ponzi.rug.title,投資詐欺
|
||||
news.ponzi.rug.desc,ポンジ・スキームの運営者が全資金を持ち逃げし、下層の投資家は全財産を失った。
|
||||
ponzi.start.sum,ポンジ・スキーム発行、日利 {0}%、宣伝費 {1} CRC
|
||||
ponzi.rug.sum,プール {0} をラグプル
|
||||
ponzi.err.wallet,発行ウォレットで署名してください。
|
||||
predict.clue.counter,情報:予定確定(カウンターの情報屋、噂のメモ)
|
||||
web3.sub.airdrop,エアドロップ
|
||||
air.h,エアドロップ
|
||||
air.none,現在受け取れるエアドロップはありません。
|
||||
air.row,{0} 報酬 {1} CRC {2} {3}日目まで
|
||||
air.claim,受け取る
|
||||
air.unlimited,{0} の無制限トークン承認
|
||||
air.limited,{0} を {1} トークン承認
|
||||
air.approvals,{0} のトークン承認
|
||||
air.approvals.none,トークン承認なし。
|
||||
air.approval,{0}:{1}
|
||||
air.revoke,取り消し
|
||||
air.sum,エアドロップ {0}({1})を受け取り
|
||||
air.claimed,{0} CRC を受け取りました。
|
||||
air.auth,ウォレットを承認
|
||||
air.unauth,未承認
|
||||
air.authed,承認済み:{0}
|
||||
air.authed.msg,{0}に対してウォレットを承認しました。
|
||||
air.auth.sum,{0}にこのウォレットでの操作を承認。範囲:{1}。
|
||||
air.err.unauth,先にこのエアドロップに対してウォレットを承認してください。
|
||||
air.revoke.sum,{0} の {1} トークン承認を取り消し
|
||||
air.revoked,トークン承認を取り消しました。
|
||||
air.err.wallet,承認したウォレットで署名してください。
|
||||
pool.h,サードパーティ収益プール(CRC)
|
||||
pool.none,現在プールはありません。
|
||||
pool.col.name,プール
|
||||
pool.col.rate,日利
|
||||
pool.col.reserve,準備金
|
||||
pool.col.lock,タイムロック
|
||||
pool.col.audit,監査
|
||||
pool.col.mine,預入額
|
||||
pool.yes,あり
|
||||
pool.no,なし
|
||||
pool.pending,出金中
|
||||
pool.closed,(閉鎖)
|
||||
pool.deposit,入金
|
||||
pool.withdraw,出金
|
||||
pool.withdraw.lock,出金を申請({0}日)
|
||||
pool.err.cap,プール上限を超過しています。残り枠: {0}。
|
||||
pool.err.none,預入残高がありません。
|
||||
pool.sum.in,{0} への入金:{1} CRC
|
||||
pool.sum.out,{0} から {1} CRC を出金
|
||||
pool.done.in,{1} に {0} CRC を入金しました。
|
||||
pool.done.out,{0} CRC を出金しました。
|
||||
pool.done.lock,{0} CRC の出金を申請しました。{1}日目に反映されます。
|
||||
nightlog.scam.drain,{0} の {1} {2} がトークン承認を通じて「{3}」に持ち去られた。
|
||||
nightlog.scam.rug,収益プール「{0}」がラグプルされ、{2} の {1} CRC が失われた。
|
||||
nightlog.scam.dry,収益プール「{0}」の準備金が底をつき閉鎖された。{2} に {1} CRC が返還された。
|
||||
nightlog.scam.paid,「{0}」からの出金が到着した:{2} が {1} CRC を受け取った。
|
||||
nightlog.scam.fakepay,偽造送金:{0}
|
||||
nightlog.scam.sent,「サポート」の安全アドレスに送金した {0} {1} は詐欺師の手に渡った。
|
||||
coinpay.intro,{0} で支払うよ。チェーン上の確認に少し時間がかかる。
|
||||
coinpay.intro.fake,{0} はもう送った、ほらスクショだ。急いでるんだ、早く品物を渡してくれ。
|
||||
coinpay.fake.entry,{0} はコインで{2}クレジット支払ったと主張して {1} を持ち去ったが、チェーン上にそのような取引は存在しない。
|
||||
scam.support.name,Poinbaseサポート
|
||||
scam.support.1,こんにちは、Poinbaseサポートです。お客様のアカウントで異常なログインが検出され、フラグ付きとなりました。
|
||||
scam.support.2,本日中に確認のため安全アドレス {1} へ {0} CRC を送金してください。確認後すぐに返金されます。
|
||||
scam.support.3,対応いただけない場合、アカウントは永久に凍結されます。では失礼します、送金を忘れずに。
|
||||
predict.sold.caught,売却時にインサイダー取引が発覚:元本と利益をすべて没収、詐欺の証拠を記録。
|
||||
predict.row.move,(昨晩 {0} {1})
|
||||
predict.stats.h,履歴(始値平均 / 実際の発生率)
|
||||
predict.stats.row,{0}:{1}件、始値平均 {2}、発生率 {3}%
|
||||
predict.kind.Event,ニュースイベント
|
||||
predict.kind.Faction,派閥作戦
|
||||
predict.kind.Purity,水の純度
|
||||
predict.kind.Price,PSC 価格
|
||||
predict.kind.Gas,ガス
|
||||
predict.kind.Cra,CRA 警戒警報
|
||||
predict.kind.Era,専用採掘機時代
|
||||
nightlog.predict.move,予測市場「{0}」が変動 {1} → {2}
|
||||
nightlog.predict.why,({0})
|
||||
chart.empty,{0}日足チャート:履歴なし。本日より記録開始。
|
||||
chart.caption,{0}日足 高 {2} 安 {3} 終 {4}({5}%)
|
||||
chart.legend,<size=80%>緑 上昇、赤 下落;黄 7日移動平均線;棒:灰 市場 / シアン プレイヤー</size>
|
||||
chart.legend.thr,<size=80%>緑 上昇、赤 下落;黄 7日移動平均線;青破線 閾値</size>
|
||||
news.story.serpico_rev.title,革命家が警察の弱みを握る
|
||||
news.story.serpico_rev.desc,革命家が警察内部の汚職証拠を入手した模様。ステーキングプールからの情報によると、革命家の準備金に多額の資金が注入され、SPARKが堅調に推移している。
|
||||
news.story.serpico_bm.title,闇市場が密約を交わす
|
||||
news.story.serpico_bm.desc,警察の内部文書が闇市場で取引された。以降、ダークネット決済は著しく安定し、CRTの償還に滞りは一切起きていない。
|
||||
news.story.serpico_sec.title,警察が内部粛清を開始
|
||||
news.story.serpico_sec.desc,警察は内部汚職の徹底調査と資金の流れの監視強化を発表した。Poinbaseは出金審査を厳格化し、ミキサーサービスが名指しされた。
|
||||
news.story.eleanor_leak.title,栄養フルーツの育種データが流出
|
||||
news.story.eleanor_leak.desc,下層の新聞社が栄養フルーツを再び結実させる研究データを公開し、パステルの株価が急落した。上層の資金を管理する保管銀行で焦げ付きが発生し、革命家が勢力を拡大している。
|
||||
news.story.eleanor_return.title,パステルが盗難データを回収
|
||||
news.story.eleanor_return.desc,パステルは盗難された研究データの回収を発表した。上層の資本勢力は安堵し、CRCの保管銀行は格付けが引き上げられた。
|
||||
news.story.lun_arrested.title,ルン警部、職権乱用で逮捕
|
||||
news.story.lun_arrested.desc,警察は職権乱用によりルン警部をその場で逮捕し、今後2週間にわたり違法取引を厳しく取り締まる方針を示した。
|
||||
tumbler.name,タンブラー
|
||||
tumbler.v1.1,やあ。ここの端末、俺のミキサーに繋がってるんだってな。
|
||||
tumbler.v1.2,あれを書いたのは俺だ。みんな俺のことをタンブラーと呼んでる。
|
||||
tumbler.v1.3,あんたの品物に触ることも、帳簿をつけることもない。コインをかき混ぜるだけだ。
|
||||
tumbler.v1.4,通りすがりだ。どんな奴が使ってるのか見てみたかったんでね。
|
||||
tumbler.v2.1,状況が怪しくなってきた。警察がオンチェーンのミキサーサービスを嗅ぎ回ってる。
|
||||
tumbler.v2.2,連中は大口のアドレスをいくつかフラグ付きにして、俺のノードまで辿ってきた。
|
||||
tumbler.v2.3,ミキサーが数日止まっても慌てるな。預けたコインが消えることはない。
|
||||
tumbler.v3.1,ノードが止められた。住処を突き止められるのも時間の問題だ。
|
||||
tumbler.v3.2,俺の手元にミキサーの署名鍵が入ったキードライブがある。
|
||||
tumbler.v3.3,警察の手に渡れば、全ユーザーの履歴が復元されてしまう。あんたのもな。
|
||||
tumbler.v3.ask,数日間、隠しておいてくれないか?
|
||||
tumbler.v3.choice.hide,[キードライブを受け取って隠す]
|
||||
tumbler.v3.choice.report,[応じるふりをして、警察に通報する]
|
||||
tumbler.v3.choice.sell,[キードライブを受け取り、闇市場に売り飛ばす]
|
||||
tumbler.v3.thanks1,助かる。数日したら取りに来る。
|
||||
tumbler.v3.thanks2,そこらに放置するなよ。家宅捜索で見つかったら、俺たち二人とも終わりだ。
|
||||
tumbler.v3.report1,……分かった。後でまた来る。
|
||||
tumbler.v4.back.1,キードライブを取りに来た。
|
||||
tumbler.v4.back.2,ノードは別の場所に移した。警察も当分は見つけられないだろう。
|
||||
tumbler.v4.back.3,お礼だ。今後はミキサーの手数料を半額にしてやる。
|
||||
tumbler.v4.lost.1,キードライブはどこだ?
|
||||
tumbler.v4.lost.2,……なくしたのか?
|
||||
tumbler.v4.lost.3,もういい。自分で何とかする。
|
||||
tumbler.v4.sold.1,キードライブを闇市場に売ったのはあんただな。
|
||||
tumbler.v4.sold.2,今じゃ連中がミキサーを牛耳ってる。手数料は倍になり、ユーザーの金はいつ持ち逃げされてもおかしくない。
|
||||
tumbler.v4.sold.3,このことは忘れないぞ。
|
||||
tumbler.v4.none.1,なんでもない。ここには来なかったことにしてくれ。
|
||||
item.keydrive.name,キードライブ
|
||||
item.keydrive.desc,タンブラーから預かったデータスティック。ミキサーの署名鍵が格納されている。禁制品:捜索で見つかった場合、犯罪証拠として記録される。
|
||||
mixer.closed,ミキサーは閉鎖され、新規の入金を受け付けていません。すでに預け入れられたコインは通常通り返還されます。
|
||||
news.tumbler.sanction.title,警察、ミキサーノードを押収
|
||||
news.tumbler.sanction.desc,警察は資金洗浄を助長したとして、オンチェーンミキサーサービスのノードを押収したと発表した。サービスは一時停止している。
|
||||
news.tumbler.caught.title,ミキサー運営者が逮捕された
|
||||
news.tumbler.caught.desc,タンブラーとして知られるミキサー運営者が下層で逮捕された。警察は、ミキサーサービスが永久に停止されたと発表した。
|
||||
news.tumbler.sold.title,ミキサーサービスが別人の手に渡る
|
||||
news.tumbler.sold.desc,下層のミキサーサービスの署名鍵が闇市場の手に渡り、手数料が即座に引き上げられたとの情報がある。ユーザーは資金の安全を懸念している。
|
||||
nightlog.tumbler.gift,タンブラーはキードライブを回収し、お礼として {0} CRT を残した({1} に送金済み)。ミキサー手数料が半減した。
|
||||
mixer.status.closed,状態:停止中
|
||||
yield.sub.pools,収益プール
|
||||
yield.sub.mine,スキーム発行
|
||||
pool.side.h,入金
|
||||
ponzi.early,ポンジ・スキームは{0}日目から発行可能。
|
||||
bpay.h,支払い
|
||||
bpay.qty,数量
|
||||
bpay.total,合計{0}クレジット相当
|
||||
bpay.need,支払額 {0} {1} ウォレット残高 {2}
|
||||
bpay.invoice,請求書を作成
|
||||
bpay.swap.h,{0} への自動変換
|
||||
bpay.swap.none,ウォレット内に十分な残高の他の通貨がありません
|
||||
bpay.swap.need,支払額 {0} {1}(スリッページ {2}% 含む)
|
||||
bpay.swap.btn,自動変換して支払う
|
||||
bpay.swap.sum,{0}:自動変換、{2} {1} を支払い、{3} に変換後に注文
|
||||
bpay.back,戻る
|
||||
cart.fab,カート {0}
|
||||
cart.h,カート
|
||||
cart.empty,カートは空です。
|
||||
cart.added,カートに追加:{0}
|
||||
cart.back,ショップに戻る
|
||||
cart.done,{0}件を決済しました。
|
||||
cart.partial,{0}件を決済、{1}件が失敗(在庫または残高不足)。
|
||||
black.info.accepts,対応通貨:{0}
|
||||
black.info.advance.yes,事前リリース対応
|
||||
black.info.advance.no,事前リリース非対応
|
||||
settings.section.ui,インターフェース
|
||||
settings.section.story,ストーリー
|
||||
settings.section.difficulty,難易度
|
||||
settings.terminal_size,取引ターミナルのサイズ
|
||||
settings.terminal_size_desc,ウィンドウサイズ(幅×高さ、UI 単位)。次にターミナルを開いたときに反映されます。
|
||||
settings.tumbler_story,タンブラーのストーリー
|
||||
settings.tumbler_story_desc,タンブラーの訪問とキードライブの依頼。オフにすると新たな訪問はなくなり、進行済みの分は保持されます。
|
||||
settings.risk_scale,リスク倍率
|
||||
settings.risk_scale_desc,詐欺、ラグプル、ウォレットポイズニング、アドレス乗っ取り、フィッシングの発生確率にかかる倍率。すべてのセーブに適用されます。
|
||||
settings.mining_scale,採掘報酬倍率
|
||||
settings.mining_scale_desc,採掘機器が受け取るブロック報酬にかかる倍率。すべてのセーブに適用されます。
|
||||
gg.header,ステーション取引委員会
|
||||
gg.p1.cap,グラフィックボード
|
||||
gg.p1.makers,ステーションには一般的なメーカーが2社ある。\n\n - Probidia(「PB」)\n - PMD(「MD」)
|
||||
gg.p1.note,メーカーを問わず、ボードの価値は本物のチップの型番定価と耐久度だけで決まる。耐久度が満タンなら定価と等しく、耐久度0では{CardValueFloor:%}だけが残る。
|
||||
gg.fan.h,ブレード
|
||||
gg.fan.0,良好(価格変わらず)
|
||||
gg.fan.1,埃あり(-{CardFanDust:%})
|
||||
gg.fan.2,欠け(-{CardFanChipped:%})
|
||||
gg.fin.h,端子
|
||||
gg.fin.0,光沢あり(価格変わらず)
|
||||
gg.fin.1,くすみ(-{CardFingersDark:%})
|
||||
gg.fin.2,酸化(-{CardFingersOxidized:%})
|
||||
gg.brk.h,ブラケット
|
||||
gg.brk.0,良好(価格変わらず)
|
||||
gg.brk.1,キズあり(-{CardBracketScratch:%})
|
||||
gg.seal.h,封印シール
|
||||
gg.seal.0,無傷(価格変わらず)
|
||||
gg.seal.2,欠損(-{CardSealMissing:%})
|
||||
gg.wear.note,ブレード、端子、ブラケットは毎晩の損耗で劣化し、悪化する一方である。封印シールは固定の特徴である。状態はハッシュレート、損耗、焼損確率にも影響する。
|
||||
gg.serial.h,シリアル番号
|
||||
gg.serial.cap,背面(シリアルシール)
|
||||
gg.serial.pb,Probidia(「PB」)\n 正規の工場コード:11、12、21、34、47
|
||||
gg.serial.md,PMD(「MD」)\n 正規の工場コード:13、22、35、41、58
|
||||
gg.print.h,背面印字
|
||||
gg.print.0,型番一致
|
||||
gg.print.1,他型番の印字(偽造品)
|
||||
gg.print.2,再印字・傾き(偽造品)
|
||||
gg.point.h,指摘
|
||||
gg.ex.card,例:{0}、耐久度{1}%
|
||||
gg.ex.base,基礎価値:+{0}
|
||||
gg.ex.fan,ブレード欠け:-{0}
|
||||
gg.ex.fin,端子のくすみ:-{0}
|
||||
gg.ex.seal,封印シール欠損:-{0}
|
||||
gg.ex.total,最終価値:{0}
|
||||
gg.ex.note,各減額は基礎価値に対する割合で計算し、合計して差し引く。
|
||||
gg.ex.fan1,ブレードに埃:-{0}
|
||||
gg.ex.fin2,端子の酸化:-{0}
|
||||
gg.ex.brk,ブラケットのキズ:-{0}
|
||||
gg.ex.nodisc,減額なし:-0
|
||||
gg.ex.fake,申告{0}、実チップ{1}:実チップで評価
|
||||
gg.ex.claimed,申告型番での価格:{0}
|
||||
gg.ex.gap,提示額との差:{0}
|
||||
gg.ex.h2,鑑定例:偽物
|
||||
gg.ex.h3,鑑定例:状態不良
|
||||
gg.ex.h4,鑑定例:軽使用
|
||||
gg.ex.h5,鑑定例:新品
|
||||
lbl.price,表示価格:{0}
|
||||
lbl.row.count,ファン数
|
||||
lbl.row.pin,電源コネクタ
|
||||
lbl.count.1,ファン1基
|
||||
lbl.count.2,ファン2基
|
||||
lbl.count.3,ファン3基
|
||||
lbl.pin.0,6ピン
|
||||
lbl.pin.1,8ピン
|
||||
lbl.pin.2,8ピン×2
|
||||
gg.p1.body,グラフィックボードはマイニングリグの中核部品であり、中古市場で最も偽造されやすい商品である。\n正規品かどうかは、ファン数、電源コネクタ、背面印字、シリアル番号の4項目で判断する。4項目すべてが表示上の型番と一致するものだけが正規品であり、1つでも合わなければ偽造品である。\nボードの価値は実際のチップの型番と状態で決まり、外観の傷みはすべて減額の対象となる。\n\n本ガイドは、グラフィックボードの鑑定に必要な知識をすべて提供する。
|
||||
gg.p2.h,ボードの型番
|
||||
gg.p2.body,型番によってファン数と電源コネクタが決まる。偽造品は、低い型番のチップに高い型番の外装を被せたもので、性能と価値は内部の実際のチップに基づく。
|
||||
gg.tier.0,RTX 60 / RX 70:6ピン、ファン1基
|
||||
gg.tier.1,RTX 70 / RX 80:8ピン、ファン2基
|
||||
gg.tier.2,RTX 80 / RX 800:8ピン、ファン3基
|
||||
gg.tier.3,RTX 90 / RX 900:8ピン×2、ファン3基
|
||||
gg.count.h,ファン数
|
||||
gg.count.body,ファン数は型番で決まる。RTX 60とRX 70は1基、RTX 70とRX 80は2基、RTX 80、RTX 90、RX 800、RX 900は3基である。\n実物のファン数が表示上の型番と合わないものは偽造品である。
|
||||
gg.pin.h,電源コネクタ
|
||||
gg.pin.body,電源コネクタも型番で決まる。RTX 60とRX 70は6ピン、RTX 70、RTX 80、RX 80、RX 800は8ピン、RTX 90とRX 900は8ピン×2である。\n実物の電源コネクタが表示上の型番と合わないものは偽造品である。
|
||||
gg.serial.body,シリアル番号はボード背面のシールに記載され、書式は、プレフィックス、型番コード、ハイフン、2桁の工場コード、ハイフン、4桁の連番の順である。例:PB2-21-6251。
|
||||
gg.serial.rule,型番コードの1~4は、順にRTX 60 / RX 70、RTX 70 / RX 80、RTX 80 / RX 800、RTX 90 / RX 900に対応する。\n型番コードが型番と合わないもの(元のチップのシリアルが貼られている)、または工場コードや桁数が不正なもの(後から貼られたシール)は偽造品である。工場コードは真贋の判定にのみ使い、価格には影響しない。
|
||||
gg.print.note,正規品となるのは、ファン数、電源コネクタ、印字、シリアル番号の4項目がすべて型番と一致する場合のみである。偽造品は少なくとも1項目が合わないが、残りが正しく作られていることもあるため、各項目を確認する。
|
||||
gg.point.body,拡大鏡で検分する。ラベルバーでは型番の行だけに「型番を指摘する」ボタンがある。その下の4行(ファン数、電源コネクタ、背面印字、シリアル番号)は閲覧のみで、ブレード、端子、ブラケット、封印シールの4つの状態の行にはそれぞれ専用の「指摘する」がある。\n隠された状態の問題を指摘すると、その行が実際の状態に変わり、価格は差額分下がる。事実でないことを指摘すると、相手は認めず、評判が下がる。\nファン数、電源コネクタ、背面印字、シリアル番号のいずれかが表示の型番と合わない場合は、型番を指摘する。そのボードは偽造品と認定され、型番は実際のチップに戻り、価格は実際のチップで再計算される。\n\n鑑定ギルドの依頼人が持ち込むボードも同様で、問題を指摘すると見積もりが変わり、最終的に正しい価値を報告する。
|
||||
gg.ex.serial,シリアル番号:{0}
|
||||
gg.ex.h,鑑定例:ブレード欠け、端子のくすみ、封印シール欠損
|
||||
rig.label.status,ステータス
|
||||
rig.st.cards,グラフィックボード数
|
||||
rig.st.power,消費電力
|
||||
rig.st.hash,ハッシュレート
|
||||
rig.st.kj,{0} kJ/日
|
||||
lbl.point.model,型番を指摘する
|
||||
col.crcprice,CRC 価格
|
||||
swap.pay,支払い
|
||||
swap.get,受取
|
||||
swap.preview,約 {0} {1} プール {2} 個、損失 {3}%
|
||||
swap.go,スワップ
|
||||
swap.same,支払いと受取は別のコインにしてください。
|
||||
mint.need,必要:{0} CRC と {1} SPARK
|
||||
mint.reserve,準備率 {0}% 担保率 {1}%
|
||||
mint.queue,処理待ち
|
||||
mint.order,{0} {1} CRA、{2}日目
|
||||
stake.coin,預入通貨
|
||||
stake.sum.via,{0} {1} をスワップ → 約 {2} CRA をステーキング
|
||||
nightlog.cra.lost,発行元から応答がありません:{0} CRA の{1}注文は失われました。
|
||||
news.crawarn.desc,革命家の準備金を数え直す者がいる。ステーキング中の CRA は全額償還できないかもしれない。解除には4日かかる。動くなら今だという声もある。
|
||||
news.cralow.desc,準備率が危うくなり、革命家は CRA のステーキング日利を元の数分の一に引き下げた。
|
||||
poin.sub.funds,資金
|
||||
funds.receive,入金
|
||||
funds.send,出金
|
||||
funds.bank,銀行口座
|
||||
funds.wallet,ウォレット
|
||||
funds.to,送金先アドレス
|
||||
funds.go,送信
|
||||
funds.sending,{0} {1} を {2} に送金中
|
||||
funds.confirm,確認 {0}/{1}
|
||||
funds.done,{0} {1} が {2} に着金しました。
|
||||
funds.done.void,{0} {1} を送金しました。アドレスに持ち主がおらず、コインは戻りません。
|
||||
funds.err.addr,無効なアドレスです。
|
||||
funds.err.self,Poinbase 自身の入金アドレスです。
|
||||
funds.err.known,そのアドレスは請求書に対する支払いのみ受け付けます。
|
||||
funds.err.fee,金額がガス代に満たません。
|
||||
wallets.sub.explorer,エクスプローラー
|
||||
explorer.search,アドレス
|
||||
explorer.all,最新
|
||||
explorer.none,送金履歴はありません。
|
||||
explorer.col.block,ブロック
|
||||
explorer.col.amount,数量
|
||||
explorer.mixer,ミキサー
|
||||
cra.mint,ミント
|
||||
cra.burn,バーン
|
||||
mint.h,公式ミント(CRC+SPARK)
|
||||
mint.sum.in,{1} CRC と {2} SPARK で {0} CRA をミント({3}~{4}日)
|
||||
mint.sum.out,{0} CRA をバーンして CRC と SPARK に({1}日)
|
||||
mint.done.in,ミントを申請しました。{0}日目に決済されます。
|
||||
mint.done.out,バーンを申請しました。{0}日目に決済されます。
|
||||
nightlog.cra.minted,ミントした {0} CRA をステーキングしました({1})。
|
||||
nightlog.cra.burned,{0} CRA をバーン:+{1} CRC、+{2} SPARK({3})。
|
||||
predict.clue.subsidy,準備金残量 {0}%。ゼロになれば必ず警告が出る
|
||||
air.noapprove,トークン許可なし
|
||||
tab.gray,グレーネット
|
||||
wallets.sub.list,ウォレット一覧
|
||||
entry.web3.l1,分散型取引と運用
|
||||
entry.mining.l1,リグの状態と夜間収益
|
||||
entry.gray.l1,ミキサーとショップ
|
||||
entry.wallets.l1,ハードウェアウォレットとエクスプローラー
|
||||
entry.wallets.l2,ウォレット {0} / {1}
|
||||
black.sell.add,出品を追加
|
||||
black.sell.back,ショーケースに戻る
|
||||
black.sell.kinds,出品中 {0}/{1} 種
|
||||
black.sell.have,出品中 {0}個
|
||||
black.sell.coins,受取コイン
|
||||
black.sell.off,取り下げ
|
||||
black.sell.off.n,取り下げ ×{0}
|
||||
black.sell.nocoin,少なくとも1種類のコインを受け付ける必要がある。
|
||||
black.sell.empty,出品中の商品はない。
|
||||
black.sell.delisted,{0}個を取り下げた。商品は保管庫に戻った。
|
||||
black.sell.partial,{0}個を出品、{1}個は出品できなかった。
|
||||
black.sell.limit.stack,同じ商品は最大{0}個まで出品できる。
|
||||
black.sell.limit.kinds,同時に出品できるのは最大{0}種類まで。
|
||||
shelf.fab,棚 {0}
|
||||
delist.fab,取り下げを確定 {0}
|
||||
black.fee.h,出品予定
|
||||
black.fee.line,{0} ×{1} 価格 {2}({3})
|
||||
black.fee.total,出品手数料 {0}
|
||||
black.fee.sum,出品手数料({0}個)
|
||||
black.sale.Sold,成約済、{0}日目に{1}で入金
|
||||
explorer.col.day,日
|
||||
explorer.day,{0}日目
|
||||
explorer.pool,RatDiggプール
|
||||
explorer.desk,Ponero両替所
|
||||
black.fee.pay,出品手数料を支払う
|
||||
explorer.col.from,送信元
|
||||
explorer.col.to,送信先
|
||||
rig.st.cond,状態
|
||||
asic.st.dead,焼損
|
||||
perp.preview,想定元本 {0} 推定平均価格 {1}(スリッページ {2}%)
|
||||
perp.sim.close,決済 想定元本 {0} 推定平均価格 {1}(スリッページ {2}%)
|
||||
perp.sim.close2,手数料 {0} 約 {1} CRC が戻る(損益 {2})
|
||||
trade.sim.sell,売却で約 {0} {1} 平均 {2} スリッページ {3}%
|
||||
trade.sim.buy,購入に約 {0} {1} 平均 {2} スリッページ {3}%
|
||||
trade.amount.unit,数量({0})
|
||||
trade.fee,手数料 {0}%
|
||||
trade.sim.thin,プールの流動性を超過
|
||||
news.wipe.down.title,{0}が1日で{1}%下落、{2}人がロスカット
|
||||
news.wipe.down.desc,この1日で{0}無期限先物のロングポジション{1}件がロスカットされ、総額は{2}クレジットに上った。Poinbaseの保険基金残高は{3}クレジット。
|
||||
news.wipe.up.title,{0}が1日で{1}%上昇、{2}人がロスカット
|
||||
news.wipe.up.desc,この1日で{0}無期限先物のショートポジション{1}件がロスカットされ、総額は{2}クレジットに上った。Poinbaseの保険基金残高は{3}クレジット。
|
||||
hot.name,売り手
|
||||
hot.intro.CRT,最近は物騒で、このCRTを持っているのは危ない。急いで現金にしたい。
|
||||
hot.intro.PSC,ある採掘場のウォレットが昨夜持ち主を変えた。PSCは今こっちにある。現金しか受け取らない。
|
||||
hot.intro.PONERO,身代金だ、Poneroで。出所は誰にも追えない。現金のみ。
|
||||
hot.offer,{0} {1}、今の相場で{2}相当だ。現金{3}で、コインはこの場で送る。
|
||||
hot.choice.yes,受け取る
|
||||
hot.choice.no,断る
|
||||
hot.say.yes,取引成立だ。
|
||||
hot.say.no,それには手を出さない。
|
||||
hot.done,送った。俺たちは会っていない。
|
||||
hot.refused,欲しがる奴はいくらでもいる。
|
||||
hot.nocash,現金も用意できないのか?ならやめだ。
|
||||
hot.nowallet,ウォレットがつながっていない。コインをどこに送れと?やめだ。
|
||||
hot.sting,動くな、警察だ。盗まれた資金の買い取りだな。現金は没収、記録にも残る。
|
||||
hw.err.poinbase,Poinbaseは{0}を受け付けない。
|
||||
@@ -0,0 +1,980 @@
|
||||
# Probably Decentralized localization table: Polish (pl)
|
||||
# AI translation, not proofread. Source: en.csv. Format: key,text (text may be quoted; \n is a line break).
|
||||
upgrade.tab,Web3
|
||||
upgrade.title,Społeczność zarządzania Web3
|
||||
upgrade.desc,"Członkowie otrzymują terminal handlowy, portfel sprzętowy, koparkę, kartę graficzną RTX 60 oraz przewodnik oceny kart graficznych. Terminal zawiera bank, giełdę Poinbase oraz strony Web3, Wydobycie i Portfele. Więcej kart i koparek sprzedaje Dr Jackson."
|
||||
item.terminal.name,Terminal handlowy
|
||||
item.terminal.desc,"Portfel, giełda Poinbase i nocny raport wydobycia."
|
||||
item.rig.name,Koparka
|
||||
item.rig.desc,Maks. liczba kart: {0}. Moc obliczeniowa {1} MH/s. Zużycie: {2} kJ dziennie
|
||||
rig.label.modules,Moduły
|
||||
item.rig.modules,"Moduły: moc obliczeniowa {0}, pobór energii {1}, zużycie {2}."
|
||||
item.rig.next,Slot {0}: przeciągnij {1} na koparkę ({2}/{3}).
|
||||
mat.common_electronic,Zwykła elektronika
|
||||
mat.rare_electronic,Rzadka elektronika
|
||||
rig.label.cards,Karty graficzne
|
||||
item.gpu.name,{0} {1}
|
||||
item.gpu.desc,Znamionowa moc obliczeniowa: {0} MH/s. Znamionowy pobór: {1} kJ dziennie Stan: {2}.
|
||||
item.gpu.burnt.name,Przepalona {0} {1}
|
||||
item.gpu.burnt.desc,Ta karta już nie działa.
|
||||
term.title,Terminal handlowy
|
||||
tab.report,Raport
|
||||
wallet.line,{0}: {1} (ok. {2} kredytów)
|
||||
wallet.empty,Portfel jest pusty.
|
||||
wallet.total,Wartość łączna: {0} kredytów
|
||||
wallet.taint,Wartość skażona: {0} kredytów
|
||||
trade.amount,Kwota
|
||||
trade.deposit,Wpłata kredytów jako CRC
|
||||
trade.withdraw,Wypłata CRC jako kredyty
|
||||
trade.pair,{0}/{1} ({2})
|
||||
trade.price,Cena {0}
|
||||
trade.buy,Kup
|
||||
trade.sell,Sprzedaj
|
||||
venue.Exchange,Poinbase
|
||||
venue.Dex,DEX
|
||||
venue.Darknet,Darknet
|
||||
msg.amount,Podaj kwotę.
|
||||
msg.balance,Niewystarczające saldo.
|
||||
msg.trade,"Zapłacono {0} {1}, otrzymano {2} {3}."
|
||||
msg.deposit,Wpłacono {0} kredytów jako CRC.
|
||||
msg.cashout,Otrzymano {0} kredytów. Podatek: {1} kredytów.
|
||||
msg.aml_light,Kontrola zgodności: wstrzymano {0} kredytów skażonych środków.
|
||||
msg.aml_heavy,Kontrola zgodności: skonfiskowano {0} kredytów skażonych środków i zgłoszono do Ochrony.
|
||||
report.none,Brak raportu wydobycia.
|
||||
report.day,Noc dnia {0}
|
||||
report.rigs,Zasilane koparki: {0} z {1}
|
||||
report.hash,Moc obliczeniowa: {0} MH/s (sieć {1} MH/s)
|
||||
report.mined,Wydobyto: {0} PSC (ok. {1} kredytów)
|
||||
report.energy,Zużyta energia: {0} kJ
|
||||
report.burnt,Przepalone karty: {0}
|
||||
report.price,Cena PSC: {0} kredytów
|
||||
nightlog.mined,Koparki wydobyły {0} PSC.
|
||||
nightlog.burnt,Karta {0} uległa przepaleniu.
|
||||
coinpay.line,Zgoda. {0} {1}.
|
||||
nightlog.coinpay,Klienci płacący monetami uregulowali {0} kredytów; monety trafiły do gorącego portfela.
|
||||
nightlog.unpowered,Koparki bez zasilania: {0}.
|
||||
news.open.title,Poinbase wprowadza PSC
|
||||
news.open.desc,Giełda Górnego poziomu Poinbase notuje teraz PSC względem CRC. Na całej stacji rośnie popyt na karty graficzne.
|
||||
news.halving.title,Nagroda za blok PSC zmniejszona o połowę
|
||||
news.halving.desc,Górnicy otrzymują teraz o połowę mniej monet co noc.
|
||||
appraisal.gpu,Karta graficzna
|
||||
dealer.name,Diler używanego sprzętu
|
||||
dealer.line1.1,Karty z likwidacji kopalni. Stan jest podany obok nazwy.
|
||||
dealer.line1.2,"Kilka kart po kopaniu, puszczę tanio."
|
||||
dealer.line1.3,Zgarnięte po drodze. Cena z pierwszej ręki.
|
||||
dealer.line2.1,"Sprawdź sam, obróć i obejrzyj tył."
|
||||
dealer.line2.2,"Brak gwarancji. Obejrzyj, zanim weźmiesz."
|
||||
dealer.line2.3,"Jak chcesz brać, cena jest do negocjacji."
|
||||
inspect.flip.back,Obróć na tył
|
||||
inspect.flip.front,Obróć na przód
|
||||
item.gpu.grade.1,jak nowy
|
||||
item.gpu.grade.2,przyzwoity
|
||||
item.gpu.grade.3,wyraźnie zużyty
|
||||
item.gpu.grade.4,mocno zużyty
|
||||
point.none.1,Nic jej nie jest. Źle spojrzałeś.
|
||||
point.none.2,"Gdzie? Nie zmyślaj, jak nie kupujesz."
|
||||
point.worn.1,"...Dobra, niech będzie. Zejdę trochę z ceny."
|
||||
point.worn.2,"Bystre oko. W porządku, niech będzie ta cena."
|
||||
point.fake.1,"...Masz mnie. Była przeflashowana. Policzę jak za to, czym naprawdę jest."
|
||||
point.fake.2,"Ech, nieoryginalny chip. Dobra, cena jak za faktyczny chip."
|
||||
lbl.fan.0,Łopatki czyste
|
||||
lbl.fan.1,Łopatki zakurzone
|
||||
lbl.fan.2,Wyszczerbiona łopatka
|
||||
lbl.fingers.0,Błyszczące
|
||||
lbl.fingers.1,Zmatowiałe
|
||||
lbl.fingers.2,Utlenione
|
||||
lbl.print.0,Zgodny z modelem
|
||||
lbl.print.1,Nadrukowano inny model
|
||||
lbl.print.2,"Przedrukowany, krzywy"
|
||||
lbl.said," (sprzedający mówił: {0})"
|
||||
lbl.point,Wskaż
|
||||
lbl.edit,Edytuj
|
||||
cust.fake.1,"To nie to, co na etykiecie. Próbujesz mi wcisnąć podróbkę?"
|
||||
cust.fake.2,Model się nie zgadza. Ten chip to zupełnie co innego.
|
||||
cust.worn.1,Nie to pisałeś. Pominąłeś wady.
|
||||
cust.worn.2,Stan na etykiecie to kłamstwo. Nie za tę cenę.
|
||||
lbl.row.fan,Łopatki
|
||||
lbl.row.fingers,Styki
|
||||
lbl.row.bracket,Zaślepka
|
||||
lbl.row.print,Nadruk z tyłu
|
||||
lbl.row.serial,Nr seryjny
|
||||
lbl.row.seal,Plomba
|
||||
lbl.bracket.0,Nienaruszona
|
||||
lbl.bracket.1,Porysowana
|
||||
lbl.serial.0,Prawidłowy
|
||||
lbl.serial.1,Zły kod fabryki lub zła długość
|
||||
lbl.serial.2,Kod modelu nie pasuje
|
||||
lbl.seal.0,Nienaruszona
|
||||
lbl.seal.2,Brak
|
||||
item.guide.name,Przewodnik oceny kart graficznych
|
||||
item.guide.desc,Przewodnik do rozpoznawania podrobionych kart graficznych i określania ich wartości.
|
||||
lbl.row.spec,Model
|
||||
news.prehalving.title,Zbliża się halving PSC
|
||||
news.prehalving.desc,Za trzy dni górnicy będą otrzymywać o połowę mniej monet na noc. Posiadacze spodziewają się wzrostu ceny.
|
||||
tab.home,Główna
|
||||
tab.bank,Bank
|
||||
tab.poinbase,Poinbase
|
||||
tab.web3,Web3
|
||||
home.enter,Wejdź
|
||||
home.open,Otwórz
|
||||
home.summary,Kredyty {0} | Aktywa on-chain ok. {1} kredytów
|
||||
home.lastnight,"Noc dnia {0}: wydobyto {1} PSC, zasilane koparki: {2} / {3}"
|
||||
entry.bank,Bank
|
||||
entry.bank.l1,"Wpłaty, wypłaty, czynsz"
|
||||
entry.bank.l2,Kredyty: {0}
|
||||
entry.poinbase,Poinbase
|
||||
entry.poinbase.l1,Giełda regulowana
|
||||
entry.poinbase.l2,PSC: {0} kredytów
|
||||
entry.web3,Web3
|
||||
entry.web3.l2,Ok. {0} kredytów
|
||||
entry.help,Pomoc
|
||||
entry.help.l1,Podręcznik Web3
|
||||
bank.cash,Kredyty: {0}
|
||||
bank.rent,"Czynsz: {0} kredytów, termin: {1} d."
|
||||
bank.crc,Konto Poinbase (CRC): {0}
|
||||
poin.account,"Konto Poinbase: CRC {0}, PSC {1}"
|
||||
avg.line,{0} – średnia cena zakupu: {1} kredytów
|
||||
avg.short,śr. zakup {0}
|
||||
avg.none,—
|
||||
col.asset,Aktywo
|
||||
col.amount,Kwota
|
||||
col.value,Wartość
|
||||
col.avg,Śr. zakup
|
||||
bank.cash.k,Kredyty
|
||||
bank.rent.k,Czynsz
|
||||
bank.rent.v,"{0}, termin: {1} d."
|
||||
bank.crc.k,Konto Poinbase (CRC)
|
||||
poin.account.h,Konto Poinbase
|
||||
trade.h,Handel
|
||||
web3.wallet.h,Portfel on-chain
|
||||
stable.ok,W parytecie
|
||||
stable.depeg,Utrata parytetu
|
||||
stable.warn,Ostrzeżenie: niskie pokrycie rezerwy stakingu
|
||||
stable.spiral,Zapaść
|
||||
aml.taint,Udział skażenia konta: {0}%
|
||||
mixer.h,Mikser
|
||||
mixer.ok,Status: działa normalnie
|
||||
mixer.sanctioned,Status: objęty sankcjami (pozostałe dni: {0}). Wypłacone w tym czasie monety zostaną oznaczone.
|
||||
mixer.pending,Oczekujące wpłaty
|
||||
mixer.none,Brak oczekujących wpłat.
|
||||
mixer.col.taint,Skażenie
|
||||
mixer.col.ready,Gotowe
|
||||
mixer.day,Dzień {0}
|
||||
mixer.deposit,Wpłata
|
||||
mixer.balance,Saldo: {1} {0}
|
||||
mixer.rounds,Rundy
|
||||
mixer.preview,"Oczekiwany zwrot: {0} {1}, skażenie niższe o ok. {2}%, gotowe w dniu {3}."
|
||||
mixer.go,Wpłać do miksera
|
||||
mixer.min,Minimalna wartość wpłaty: {0} kredytów.
|
||||
mixer.done,Wpłacono {0} {1}; zwrot w dniu {2}.
|
||||
mixer.upgrade.title,Mikser
|
||||
mixer.upgrade.desc,"Odblokowuje mikser w zakładce Szara sieć terminala: wpłacaj skażone monety i odbieraj je po kilku dniach z mniejszym skażeniem. Wypłata świeżo zmiksowanych monet podlega surowszej kontroli; podczas obławy mikser może zostać objęty sankcjami, a wypłacone w tym czasie monety zostaną oznaczone."
|
||||
news.sanction.title,Mikser wpisany na listę sankcyjną
|
||||
news.sanction.desc,Ochrona objęła sankcjami grupę usług miksujących. Środki wypłacone z mikserów w ciągu najbliższych kilku dni będą traktowane jako podejrzane.
|
||||
nightlog.mixer,Mikser zwrócił {0} {1}; skażenie {2} -> {3}.
|
||||
nightlog.mixer_flag," (wypłacono w trakcie sankcji; adres oznaczony)"
|
||||
nightlog.mixer_rug,Operator miksera uciekł ze środkami: {0} {1} nigdy nie wróciło.
|
||||
web3.sub.trade,Handel
|
||||
gray.sub.mixer,Mikser
|
||||
msg.frozen,Te monety są zamrożone do czasu ich odmrożenia.
|
||||
wallet.frozen,"{0}: {1} zamrożone, odmrożenie w dniu {2}"
|
||||
nightlog.crt_freeze,Czarny Rynek przekazał adresy podczas obławy: {0} twojego CRT zostało zamrożone do dnia {1}.
|
||||
nightlog.thaw,Zamrożone {0} {1} zostało odmrożone.
|
||||
news.crtfreeze.title,Czarny Rynek zamraża część adresów CRT w ramach obławy
|
||||
news.crtfreeze.desc,"Krążą plotki, że Czarny Rynek przekazał Ochronie listę adresów CRT w zamian za spokój. Posiadacze o niskiej reputacji mają większe szanse na zamrożenie środków."
|
||||
black.upgrade.title,Sklep Web3
|
||||
black.upgrade.desc,"Odblokowuje sklep w zakładce Szara sieć terminala: ramię Czarnego Rynku on-chain. Cotygodniowe dostawy kontrabandy, sporadycznie zaawansowana technologia i karty graficzne (z marżą); kupuj od ręki lub zamawiaj z dostawą przez kuriera. Płatność wyłącznie kryptowalutami (PSC, CRT, CRA, Ponero), akceptowane także skażone monety. Wymaga reputacji na Czarnym Rynku; niedostępne w trakcie obławy."
|
||||
black.offline,Wejście on-chain do sklepu jest niedostępne w trakcie obławy.
|
||||
black.closed,Wymagana reputacja na Czarnym Rynku: {0} (obecnie: {1}).
|
||||
black.sub.buy,Kup
|
||||
black.shop.h,Sprzedaż od ręki
|
||||
black.rep,Reputacja na Czarnym Rynku: {0}
|
||||
black.empty,Wyprzedane na ten tydzień.
|
||||
black.offer,{0} x{1} {2} kredytów
|
||||
black.buy,Kup
|
||||
black.bought,Transakcja zakończona: {0} trafia do magazynu.
|
||||
black.pay.h,Płatność
|
||||
black.desk.h,Kantor Ponero
|
||||
black.desk.left,Pozostało dzisiaj: {0} (limit: {1})
|
||||
black.desk.price,Cena Ponero: {0}
|
||||
black.desk.swap,Wymiana
|
||||
black.desk.in,Na Ponero
|
||||
black.desk.out,Z Ponero
|
||||
black.desk.go,Wymień
|
||||
black.desk.fail,"Wymiana nie powiodła się: nieprawidłowe saldo, limit lub kwota."
|
||||
black.sub.orders,Zamówienia
|
||||
black.rugged,Platforma padła; nikt jej nie otworzy przez kolejne {0} dni.
|
||||
black.seller,"Transakcje: {1}, pozytywne: {2}%"
|
||||
black.orders.h,Katalog zamówień
|
||||
black.order,Zamów
|
||||
black.mode.Escrow,Depozyt
|
||||
black.mode.Advance,Wypłata zaliczkowa
|
||||
black.ordered,"Zamówiono: {0}, dostawa w dniu {1}."
|
||||
black.mine.h,Moje zamówienia
|
||||
black.mine.none,Brak zamówień.
|
||||
black.mine.line,"{0} ({1}, {2}): {3}, dzień {4}"
|
||||
black.state.Pending,w drodze
|
||||
black.state.Ready,dostarczono
|
||||
black.state.Done,odebrano
|
||||
black.state.Refunded.scam,"sprzedający uciekł, zwrócono środki"
|
||||
black.state.Lost.scam,"sprzedający uciekł, środki przepadły"
|
||||
black.state.Lost.rug,"rug pull platformy, środki przepadły"
|
||||
black.state.Lost.intercept,przechwycono
|
||||
black.forum.h,Informacje z forum
|
||||
black.forum.quiet,Ostatnio panuje spokój.
|
||||
black.forum.scam,"Krążą głosy, że {0} bierze pieniądze i nie wysyła towaru."
|
||||
black.forum.rug,"Wypłaty ostatnio zwalniają, strona kusi promocjami, a wiele wątków ze skargami zostało usuniętych."
|
||||
nightlog.bm.scam_refund,Czarny Rynek: sprzedający {0} uciekł; depozyt za {1} został zwrócony.
|
||||
nightlog.bm.scam_loss,Czarny Rynek: sprzedający {0} wziął zaliczkę i uciekł; {1} przepadło ({2} kredytów).
|
||||
nightlog.bm.intercept,Czarny Rynek: paczka zawierająca {0} została przechwycona; utracono płatność w wysokości {1} kredytów.
|
||||
nightlog.bm.rug,Czarny Rynek: nastąpił rug pull platformy; środki w tranzycie za {0} ({1}) przepadły.
|
||||
nightlog.bm.reopen,Czarny Rynek: ktoś otworzył interes w starym miejscu.
|
||||
news.bmrug.title,Rug pull na platformie Czarnego Rynku
|
||||
news.bmrug.desc,"Wejście on-chain Czarnego Rynku zniknęło z dnia na dzień, co doprowadziło do utraty wszystkich środków z depozytów i wypłat zaliczkowych. Nowy punkt dostępowy pojawi się za kilka dni."
|
||||
courier.name,Kurier
|
||||
courier.line1.1,Dostawa na miejscu.
|
||||
courier.line1.2,Paczka dla ciebie.
|
||||
courier.line2.1,"Nie mów mi, co jest w środku. Wolę nie wiedzieć."
|
||||
courier.line2.2,Zostawiam tutaj. Znikam.
|
||||
gray.sub.black,Sklep
|
||||
black.stock,Pozostało: {0}
|
||||
black.price,{0} kredytów
|
||||
black.noadvance,Brak wypłat zaliczkowych
|
||||
black.kind.gpu,GPU stan: {0}%
|
||||
black.kind.Contraband.1,Kontrabanda (niski poziom)
|
||||
black.kind.Contraband.2,Kontrabanda (średni poziom)
|
||||
black.kind.Contraband.3,Kontrabanda (wysoki poziom)
|
||||
black.kind.Tech,Zaawansowana technologia (marża)
|
||||
nightlog.bm.ready,Czarny Rynek: {0} na miejscu; kurier pojawi się po otwarciu lokalu.
|
||||
guide.web3.title,Podręcznik Web3
|
||||
guide.web3.text,"Bank i handel: strona banku jest tylko do odczytu i pokazuje gotówkę, czynsz oraz CRC na koncie Poinbase. Strona Środki w Poinbase obsługuje wpłaty i wypłaty; najpierw wybiera się monetę: CRC może iść przez konto bankowe lub portfel, pozostałe monety tylko przez portfel. Wpłata z banku zamienia kredyty na CRC na koncie Poinbase; wypłata do banku zamienia CRC z powrotem na kredyty i podlega kontroli zgodności, sprawdzającej skażenie konta Poinbase. Wypłata do portfela wymaga podania adresu odbiorcy i kilku potwierdzeń do zaksięgowania; opłata gas jest stała, na poziomie normalnym, i pobierana z wysyłanej monety. Błędny format adresu lub cyfra kontrolna powoduje odrzucenie; adres o poprawnym formacie, którego nikt nie używa, oznacza utratę wysłanych monet.¶Handel: PSC to skrót od Probably Stolen Coin, monety wydobywanej przez karty graficzne i koparki. Rynek spot Poinbase ma dwie pary, PSC/CRC i SPARK/CRC, zależnie od monety wybranej na wykresie. Zarówno zakup, jak i sprzedaż wpisuje się jako ilość monety bazowej; podgląd pokazuje zapłaconą lub otrzymaną monetę kwotowaną, średnia cena zawiera prowizję, a poślizg nie.¶Strona handlu Web3 pozwala wymienić dowolne dwie monety, zawsze przez CRC: gdy CRC jest po jednej stronie, używana jest jedna pula, w przeciwnym razie dwie, z dwiema opłatami i sumującym się poślizgiem; podgląd pokazuje otrzymaną ilość, liczbę pul i stratę. Wymiany między stablecoinami (CRT lub CRA na CRC) idą przez pule stabilne: prowizja {StableFee:%} i prawie zerowy poślizg blisko powiązania; przy utracie powiązania płynność maleje, a przy krachu zostaje wycofana i poślizg gwałtownie rośnie.§Portfele sprzętowe: monety w łańcuchu znajdują się w portfelach sprzętowych PLEDGER, a każdy z nich ma własne saldo i poziom skażenia. Portfel jest przedmiotem: przeciągnij go na terminal handlowy, aby go załadować. Otwórz go na stronie Portfele w terminalu; połącz i odłącz w prawym górnym rogu terminala. Handel na stronie Web3 oraz sklep i mikser na stronie Szara sieć korzystają z połączonego portfela; bez portfela lub bez połączenia są tylko do odczytu, a wszystkie salda wynoszą 0. Klienci płacący monetami płacą na połączony portfel.¶Płatności (sklep, mikser, kantor Ponero, opłaty za wystawienie) zaczynają się od rachunku w terminalu; wpisz adres odbiorcy w portfelu i przytrzymaj ✓, aby podpisać. Dwa ostatnie znaki adresu to suma kontrolna, więc pomyłka o jeden znak jest zwykle wychwytywana; sporadycznie zdarza się, że okazuje się poprawny i monety trafiają pod adres, z którego nikt nie korzysta. Wymiany na DEX również wymagają podpisu na portfelu.¶Poinbase to konto powiernicze; wpłaty wysyła się z portfela na adres wpłat Poinbase (tylko PSC, CRC i SPARK; regulowana giełda nie przyjmuje CRT Czarnego Rynku ani CRA Rewolucji, a portfel blokuje wysłanie ich na adres wpłat), a wypłaty zleca się na stronie Środki w Poinbase. Eksplorator na stronie Portfele pozwala sprawdzać przelewy według adresu i pokazuje wyłącznie przelewy, które faktycznie miały miejsce: każdy ruch do i z twoich portfeli (przelewy, wymiany na DEX i inne wywołania kontraktów, zyski koparek, wypłaty, monety wysyłane ci przez innych); Ponero to moneta prywatności i nigdy się nie pojawia. Więcej portfeli sprzętowych sprzedaje Dr Jackson; przeciągnij portfel na terminal handlowy, aby go dodać – maksymalnie do {WalletMax}. W sklepie dostępne są tańsze. Niepotrzebny portfel można zniszczyć na stronie Portfele; jego monety przepadają na zawsze, podobnie jak wszystko, co zostanie później wysłane na jego adres.¶Przelewy wymagają opłaty gas: wolnej, normalnej lub szybkiej, a ceny gasu rosną i spadają w cyklu około tygodnia; gdy sieć jest przeciążona, opłaty gas rosną, a powolne transakcje mogą zostać usunięte z mempoola. Przed wysłaniem sprawdź pełny adres.§Staking: CRA ulokowane w puli Rewolucji przynosi dzienny zysk według stawki dziennej, doliczany do wkładu; wypłata wymaga wcześniejszego złożenia wniosku i odczekania czterech dni, bez naliczania odsetek w okresie oczekiwania i bez możliwości wcześniejszego odbioru. CRA jest częściowo zabezpieczone: każde CRA wspierają rezerwa CRC należąca do Rewolucji oraz token równoważący SPARK; pokrycie rezerwy i stopa zabezpieczenia widnieją na stronie stakingu. Odsetki wypłacane są w nowych, niezabezpieczonych CRA, co rozwadnia pokrycie rezerwy, tym szybciej, im więcej w stakingu; przy zbyt niskim pokryciu Rewolucja obniża stawkę. Rewolucja czasem sięga po rezerwę, a wcześniej krążą pogłoski: to zapowiedź. Jeśli potem pokrycie spadnie poniżej {CraCrashRatio:%}, następuje krach: CRA staje się bezwartościowe w ciągu trzech dni, a cztery dni na odblokowanie to za wolno; powyżej tego progu jest tylko dyskonto, a środki z grabieży Górnego poziomu stopniowo odbudowują rezerwę.Line truncated
|
||||
courier.odd1,...Paczka dotarła.
|
||||
courier.odd2,(Trzyma rękę w kieszeni.) Podpisz tutaj.
|
||||
courier.sign,Podpisz
|
||||
courier.refuse,Odmów
|
||||
courier.signed,"Świetnie. Nie ruszaj się, Ochrona."
|
||||
courier.refused,"...Dobra, nieważne."
|
||||
black.state.Lost.seized,skonfiskowano
|
||||
black.state.Lost.refused,odrzucono
|
||||
black.forum.easy,"Ostatnio idzie zbyt gładko: sprzedający wysyłają szybciej niż kiedykolwiek i pojawiły się nowe konta, których nikt nie widział."
|
||||
black.forum.busted,"Chodzą słuchy, że {0} trafił do aresztu, a historia zamówień wciąż istnieje."
|
||||
nightlog.bm.trap.honeypot,"Czarny Rynek: platforma została przejęta przez służby; twój zakup {0} został namierzony, odnotowano przestępstwo: {1}."
|
||||
nightlog.bm.trap.seller,"Czarny Rynek: sprzedający trafił do aresztu, a historia zamówień obciąża ciebie: {0}, odnotowano przestępstwo: {1}."
|
||||
tab.mining,Wydobycie
|
||||
courier.sign.say,Podpiszę.
|
||||
courier.refuse.say,Nie biorę tego. Odeślij to.
|
||||
black.forum.busted_buyer,"Chodzą słuchy, że grupa kupujących trafiła do aresztu, a historia sprzedaży nadal jest na platformie."
|
||||
nightlog.bm.sale_sold,Czarny Rynek: twoja oferta {0} została sprzedana za {1}; wypłata: dzień {2}.
|
||||
nightlog.bm.sale_paid,"Czarny Rynek: wypłata {1} za {0} dotarła (CRT), skażenie: {2}."
|
||||
nightlog.bm.sale_fake,"Czarny Rynek: kupujący zorientował się, że {0} to podróbka i zwrócił towar; twoja ocena spadła."
|
||||
nightlog.bm.sale_rug,Czarny Rynek: platforma zrobiła rug pull; twoje {0} i wypłata ({1}) przepadły.
|
||||
black.sub.sell,Sprzedaż
|
||||
black.sell.h,Sprzedaż
|
||||
black.sell.mult,Mnożnik ceny
|
||||
black.sell.none,Brak przedmiotów na sprzedaż w magazynie.
|
||||
black.sell.rating,Ocena {0}%
|
||||
black.mine.sale,{0} ref {1} cena {2} (x{3}): {4}
|
||||
black.sale.Listed,wystawiono
|
||||
black.sale.Paid,wypłacono
|
||||
black.sale.Lost,"rug pull platformy, przepadło"
|
||||
black.sale.Delisted,wycofano
|
||||
black.sale.Delisted.fake,kupujący wykrył podróbkę i zwrócił towar
|
||||
black.kind.gpunew,Karta graficzna nowa
|
||||
merchant.GpuNew,Nowe karty graficzne
|
||||
merchant.GpuUsed,Używane karty graficzne
|
||||
merchant.Arms,Broń
|
||||
merchant.Docs,Karty dostępu i chipy
|
||||
merchant.Pharma,Farmaceutyki
|
||||
merchant.Bulk,Towary masowe
|
||||
black.days,Dostawa: {0} d.
|
||||
black.sell.listedall,Wystawiono: {0} szt.
|
||||
merchant.Rigs,Koparki i zasilanie
|
||||
merchant.Modules,Moduły
|
||||
merchant.GunMods,Części rusznikarskie
|
||||
merchant.Chem,Chemikalia
|
||||
merchant.Brewer,Piwowarstwo
|
||||
merchant.Farm,Hydroponika
|
||||
merchant.Husbandry,Hodowla
|
||||
merchant.Miner,Sprzęt górniczy
|
||||
merchant.Water,Woda
|
||||
merchant.Storage,Magazyn
|
||||
merchant.Tools,Narzędzia
|
||||
merchant.Luxury,Luksus
|
||||
black.kind.Goods,Towary
|
||||
merchant.Elite,Sklep elitarny
|
||||
merchant.Personal,Sprzedawca prywatny
|
||||
black.pay.confirm,Rachunek
|
||||
black.pay.to,Adres odbiorcy: {0}
|
||||
black.pay.cancel,Unieważnij
|
||||
pay.mix,Mikser {0} {1}
|
||||
pay.swap,Kantor Ponero {0} {1}
|
||||
black.edit.cancel,Anuluj
|
||||
merchant.Platform,Platforma
|
||||
black.platform.line,Spot platformy natychmiastowa dostawa
|
||||
black.orders.in,Kupione
|
||||
black.orders.out,Sprzedawane
|
||||
black.desk.pair,PONERO [moneta prywatności] cena {0}
|
||||
black.pay.amount,Kwota: {0} {1} (około {2} kredytów)
|
||||
black.pay.wallet,Zapłać z portfela
|
||||
hw.total,Łącznie ≈ {0} kredytów
|
||||
hw.pending.bill,Do zapłaty: {0}
|
||||
hw.pending.sign,Do podpisu: {0}
|
||||
hw.send,Wyślij
|
||||
hw.review,Prośba o podpis
|
||||
hw.to,Adres odbiorcy
|
||||
hw.avail,Dostępne {1} {0}
|
||||
hw.amount,Kwota
|
||||
hw.bill,Rachunek: {0} {1} {2}
|
||||
hw.fill,Wpisz kwotę rachunku
|
||||
hw.next,✓ Dalej × Wstecz
|
||||
hw.err.format,Nieprawidłowy format adresu.
|
||||
hw.err.checksum,Błąd sumy kontrolnej adresu.
|
||||
hw.err.self,To jest adres własny tego portfela.
|
||||
hw.err.asset,Rachunek wymaga {0}.
|
||||
hw.err.short,Mniej niż na rachunku: {0} {1}.
|
||||
hw.err.nobill,Brak nieopłaconych rachunków dla tego odbiorcy.
|
||||
hw.review.h,Podsumowanie
|
||||
hw.contract,Wywołanie kontraktu
|
||||
hw.review.to,Adres odbiorcy
|
||||
hw.review.amount,{0} {1} (około {2} kredytów)
|
||||
hw.review.bill,Rachunek: {0}
|
||||
hw.review.unknown,Brak historii transakcji dla tego adresu.
|
||||
hw.review.over,Nadpłata {0} {1}; brak zwrotu.
|
||||
hw.hold,"Przytrzymaj ✓, aby podpisać × Odrzuć"
|
||||
hw.tx.h,Transakcja
|
||||
hw.tx.signing,Podpisywanie…
|
||||
hw.tx.mempool,Rozesłano; oczekiwanie w mempoolu…
|
||||
hw.tx.packed,Dołączono do bloku #{0}
|
||||
hw.tx.confirm,Blok #{0} potwierdzenie {1}/{2}
|
||||
hw.skip,Pomiń
|
||||
hw.done.h,Potwierdzono
|
||||
hw.done.block,Blok #{0}
|
||||
hw.done.sent,{0} {1} → {2}
|
||||
hw.done.void,Nikt nie używa tego adresu. Środki przepadły.
|
||||
hw.back,Wstecz
|
||||
hw.rejected,Odrzucono podpis na portfelu.
|
||||
hw.wait,Potwierdź na portfelu.
|
||||
hw.swap,Wymiana {0} {1} → około {2} {3}
|
||||
tab.wallets,Portfele
|
||||
hw.wallet.n,Portfel {0}
|
||||
hw.review.own,Własny portfel: {0}
|
||||
hw.review.poinbase,Adres wpłaty Poinbase
|
||||
poin.deposit,Adres wpłaty: {0}
|
||||
wallets.count,Portfele {0}/{1}
|
||||
wallets.col.name,Nazwa
|
||||
wallets.col.addr,Adres
|
||||
wallets.col.taint,Skażone
|
||||
wallets.open,Otwórz
|
||||
wallets.use,Połącz
|
||||
wallets.current,Połączono
|
||||
wallets.added,Dodano {0}: {1}
|
||||
nightlog.drained,"Monety z {0} zostały wyprowadzone, około {1} kredytów."
|
||||
item.hwwallet.name,Portfel sprzętowy PLEDGER
|
||||
item.hwwallet.desc,"Portfel sprzętowy z dużym ekranem. Przeciągnij go na terminal handlowy, aby dodać portfel (maks. 5)."
|
||||
poin.empty,Konto jest puste.
|
||||
hw.copy,Kopiuj
|
||||
hw.paste,Wklej
|
||||
hw.copied,Skopiowano adres.
|
||||
hw.copied.addr,Skopiowano {0}
|
||||
hw.balance.frozen," (zamrożone {0})"
|
||||
wallets.destroy,Zniszcz
|
||||
wallets.destroy.sure,Potwierdź
|
||||
wallets.destroyed,Zniszczono {0}: {1}
|
||||
wallets.destroy.warn,"Zniszczenie {0} oznacza trwałą utratę jego monet. Naciśnij ponownie, aby potwierdzić."
|
||||
payout.label,Wypłata
|
||||
payout.unset,Nie ustawiono
|
||||
payout.set,Ustaw adres
|
||||
payout.h,Adres wypłaty
|
||||
payout.cur,Obecny: {0}
|
||||
payout.pick,Własne portfele:
|
||||
payout.manual,Lub wpisz adres:
|
||||
payout.clear,Wyczyść
|
||||
payout.err,Nieprawidłowy adres.
|
||||
nightlog.mined.lost,Utracono {0} wydobytych PSC: brak ustawionego adresu wypłaty albo jego portfel został zniszczony.
|
||||
wallets.none,Brak załadowanego portfela. Przeciągnij portfel sprzętowy na terminal.
|
||||
web3.err.noconn,Brak połączonego portfela.
|
||||
web3.connect,Połącz portfel
|
||||
web3.disconnect,Odłącz
|
||||
web3.conn,{0} {1}
|
||||
hw.balance.value,≈ {0}
|
||||
wallets.rename,Zmień nazwę
|
||||
wallets.rename.h,Nowa nazwa dla {0}
|
||||
wallets.rename.ok,OK
|
||||
hw.fee.slow,Wolno
|
||||
hw.fee.normal,Normalnie
|
||||
hw.fee.fast,Szybko
|
||||
hw.fee,Opłata gas {0} {1} (około {2} kredytów)
|
||||
hw.confs,Wymagane potwierdzenia: {0}
|
||||
hw.congested,Sieć przeciążona
|
||||
hw.congested.slow,Sieć przeciążona: niska opłata może spowodować usunięcie z mempoola
|
||||
hw.recent,Ostatnie
|
||||
hw.recent.out,→ {0} {1} {2}
|
||||
hw.recent.in,← {0} {1} {2}
|
||||
hw.review.history,Adres obecny w historii
|
||||
hw.tx.stuck,W kolejce w mempoolu…
|
||||
hw.tx.dropped,Usunięto z mempoola. Nic nie wysłano; opłata gas została pobrana.
|
||||
hw.dropped.h,Nie wysłano
|
||||
hw.err.fee,Za mało środków na pokrycie opłaty gas.
|
||||
news.congest.title,Przeciążenie łańcucha
|
||||
news.congest.desc,"Szał wokół airdropu zablokował łańcuch. Opłaty gas wzrosły kilkukrotnie, a transakcje z niską opłatą gas mogą zostać usunięte z mempoola."
|
||||
news.phish.title,Komunikat Poinbase: migracja adresu wpłat
|
||||
news.phish.desc,Poinbase zaktualizowało system portfeli. Stary adres wpłat zostanie wycofany; prosimy przesyłać aktywa na nowy adres {0}.
|
||||
black.forum.phish,"Ktoś opublikował nowy adres miksera: {0}, twierdząc, że stary jest obserwowany."
|
||||
hw.gas,Gas ×{0}
|
||||
web3.sub.stake,Staking
|
||||
stake.h,Pula stakingowa Rewolucji
|
||||
stake.rate,Stawka dzienna {0}%; oczekiwanie na wypłatę: {1} d. bez odsetek
|
||||
stake.low,Niskie pokrycie rezerwy; stawka obniżona
|
||||
stake.cra,Cena CRA {0} {1}
|
||||
stake.none,Brak środków w stakingu.
|
||||
stake.col.wallet,Portfel
|
||||
stake.col.amount,W stakingu
|
||||
stake.col.queue,Odblokowanie
|
||||
stake.day," (dzień {0})"
|
||||
spark.price,Token równoważący SPARK {0} kredytów
|
||||
stake.ops,{0}
|
||||
stake.avail,CRA {0} W stakingu {1}
|
||||
stake.do,Stakuj
|
||||
stake.undo,Zgłoś wypłatę
|
||||
stake.sum.in,Zastakuj {0} CRA
|
||||
stake.sum.out,Zgłoś wypłatę {0} CRA (dostępne za: {1} d.)
|
||||
stake.done.in,Zastakowano {0} CRA.
|
||||
stake.done.out,Zgłoszono wypłatę {0} CRA; powrót do portfela w dniu {1}.
|
||||
nightlog.stakeint,Odsetki ze stakingu +{0} CRA.
|
||||
nightlog.unstaked,{0} CRA wycofane ze stakingu zwrócono do {1}.
|
||||
news.crawarn.title,Niepokoje wokół puli stakingowej Rewolucji
|
||||
news.cralow.title,Rewolucja obniża stawkę stakingu
|
||||
stake.avail2,SPARK {0}
|
||||
poin.sub.spot,Spot
|
||||
poin.sub.perp,Wieczyste
|
||||
perp.h,Kontrakty wieczyste
|
||||
perp.acct,Konto depozytu zabezpieczającego CRC {0}
|
||||
perp.debt,Zadłużenie {0}; zajęcie przedmiotów za {1} d. Brak nowych pozycji i wypłat do momentu spłaty.
|
||||
perp.banned,Konto kontraktów wieczystych zablokowane jeszcze na: {0} d.
|
||||
perp.none,Brak pozycji.
|
||||
perp.col.pos,Pozycja
|
||||
perp.col.notional,Wartość nominalna
|
||||
perp.col.price,Wejście → cena
|
||||
perp.col.pnl,PnL
|
||||
perp.col.liq,Cena likwidacji
|
||||
perp.long,Długa
|
||||
perp.short,Krótka
|
||||
perp.rate,{0} cena {1} finansowanie {2}%/noc
|
||||
perp.fund,Fundusz ubezpieczeniowy {0}
|
||||
perp.open,Otwórz
|
||||
perp.margin,Kwota depozytu (CRC)
|
||||
perp.do.open,Otwórz
|
||||
perp.do.add,+ Depozyt
|
||||
perp.do.close,Zamknij
|
||||
perp.opened,"Otwarto {0} {1}: depozyt {2} CRC, {3}×."
|
||||
perp.added,Dodano {0} CRC depozytu.
|
||||
perp.closed,Zamknięto; {0} CRC wróciło na konto (PnL {1}).
|
||||
perp.deficit,Niedobór kapitału {0} pokryto z funduszu ubezpieczeniowego i długu.
|
||||
perp.err.Banned,Konto kontraktów wieczystych jest zablokowane.
|
||||
perp.err.Debt,Posiadasz zadłużenie; brak możliwości otwierania nowych pozycji.
|
||||
perp.err.Leverage,Dźwignia przekracza limit dla tego produktu.
|
||||
perp.err.Size,Przekroczono limit wielkości pozycji dla tego produktu.
|
||||
perp.err.Funds,Niewystarczająca ilość CRC na koncie (wliczając opłatę).
|
||||
perp.err.Opposite,Nie można jednocześnie posiadać pozycji długiej i krótkiej na tym samym produkcie; najpierw zamknij istniejącą.
|
||||
perp.err.NoPosition,Brak pozycji.
|
||||
perp.err.Margin,Wprowadź kwotę depozytu zabezpieczającego.
|
||||
perp.debt.block,Masz dług wobec biura kontraktów; wypłaty zablokowane.
|
||||
nightlog.perp.liq,Pozycja {0} została zlikwidowana; depozyt {1} przepadł.
|
||||
nightlog.perp.adl,Fundusz ubezpieczeniowy wyczerpał się; dla {0} uruchomiono auto-delewarowanie i potrącono {1} zysku.
|
||||
nightlog.perp.interest,Naliczono odsetki od długu z kontraktów wieczystych; łączne zadłużenie wynosi {0}.
|
||||
nightlog.perp.seize,Zaległy dług z kontraktów wieczystych: zajęte przedmioty pokryły {0}.
|
||||
nightlog.perp.writeoff," Odpisano {0}; konto kontraktów wieczystych zablokowane na {1} d."
|
||||
perp.slip.title,Pokwitowanie zajęcia za dług z kontraktów wieczystych
|
||||
perp.preview2,Prowizja {0} Likw. {1}
|
||||
nightlog.perp.repaid,Niedobór na kontraktach wieczystych: pobrano {0} CRC z konta Poinbase na spłatę.
|
||||
perp.err.Thin,"Poślizg tego zlecenia jest tak duży, że nastąpi natychmiastowa likwidacja. Zmniejsz wielkość lub dźwignię."
|
||||
perp.err.Single,Tylko jedna pozycja naraz; dołóż depozyt.
|
||||
mat.hypertech_electronic,Komponent elektroniczny Hypertech
|
||||
item.asic.name,Koparka RatDigg {0}
|
||||
item.asic.dead.name,Przepalona koparka RatDigg {0}
|
||||
item.asic.desc,"Znamionowa moc: {0} GH/s. Znamionowy pobór: {1} kJ dziennie Stan: {2}. Samodzielna koparka: wymaga baterii do działania, przyjmuje moduły."
|
||||
item.asic.dead.desc,"Przepalona. Przeciągnij na nią komponenty elektroniczne, aby ją naprawić: obecnie {0} × {1}. Kondycja spada o 20 po naprawie."
|
||||
item.asic.dead.fixed,Już naprawiono.
|
||||
merchant.Asic,Diler koparek
|
||||
black.kind.asic,Koparka stan {0}%
|
||||
black.kind.asicnew,Koparka nowa
|
||||
news.erawarn.title,RatDigg wkrótce wprowadzi nową generację koparek
|
||||
news.erawarn.desc,"Producent dedykowanych koparek zapowiedział nowy sprzęt, a branża spodziewa się masowej wymiany w dużych kopalniach. Mówi się, że dobre czasy wydobycia na kartach graficznych dobiegają końca."
|
||||
news.era.title,Era koparek
|
||||
news.era.desc,"Nowa generacja dedykowanych koparek trafiła do masowej produkcji, a duże kopalnie zmniejszyły koszty energii o połowę. Moc obliczeniowa sieci wzrośnie, a zyski górników korzystających z kart graficznych ulegną rozmyciu."
|
||||
web3.sub.predict,Predykcje
|
||||
predict.h,Rynki predykcyjne
|
||||
predict.acct,{0}: CRC {1}
|
||||
predict.none,Brak dziś otwartych rynków.
|
||||
predict.closed,zamknięty
|
||||
predict.row,Tak {0} Nie {1}
|
||||
predict.held,"posiadane {0} x{1}, koszt {2}"
|
||||
predict.yes,Tak
|
||||
predict.no,Nie
|
||||
predict.void,unieważniony
|
||||
predict.result,Dzień {0} {1} wynik: {2} {3}
|
||||
predict.pick,Handel
|
||||
predict.price,Cena za udział: Tak {0} Nie {1}
|
||||
predict.pos,{0}: {1} x{2}
|
||||
predict.pos2,Koszt {0} wypłata {1}
|
||||
predict.sum.buy,Kup {1} za {2} CRC: {0}
|
||||
predict.sum.sell,Sprzedaj pozycję predykcyjną: {0}
|
||||
predict.closed.note,"Zamknięty, oczekiwanie na rozliczenie."
|
||||
predict.preview,"Kup {0}: ok. {1} udziałów (śr. {2}), zysk netto {3} przy trafieniu"
|
||||
predict.buy.yes,Kup: Tak
|
||||
predict.buy.no,Kup: Nie
|
||||
predict.sell,Sprzedaj wszystko
|
||||
predict.bought,"Kupiono {0} za {2}, wypłata {1} w przypadku trafienia."
|
||||
predict.sold,"Sprzedano, otrzymano {0}."
|
||||
predict.err.Closed,Ten rynek jest zamknięty.
|
||||
predict.err.Amount,Nieprawidłowa kwota.
|
||||
predict.err.Funds,Niewystarczająca ilość CRC w portfelu.
|
||||
predict.err.Cap,Przekroczono limit pozycji dla tego rynku.
|
||||
predict.err.Opposite,Posiadasz przeciwną pozycję; najpierw ją sprzedaj.
|
||||
predict.err.NoPosition,Brak pozycji na tym rynku.
|
||||
predict.win.one,Dzień {0}
|
||||
predict.win.range,Dni {0}–{1}
|
||||
predict.q.event,{0}: nastąpi „{1}”
|
||||
predict.q.faction,{0}: {1} rozpocznie operację
|
||||
predict.q.purity,{0}: czystość {1} >= {2}
|
||||
predict.q.price,{0}: cena {1} >= {2}
|
||||
predict.faction.FACTION_SECURITY,Ochrona
|
||||
predict.faction.FACTION_REVOLUTION,Rewolucja
|
||||
predict.faction.FACTION_LOWER_LEVEL,Dolny poziom
|
||||
predict.faction.FACTION_UPPER_LEVEL,Górny poziom
|
||||
predict.faction.FACTION_BLACK_MARKET,Czarny Rynek
|
||||
predict.purity.gutter,Woda z Dolnego poziomu
|
||||
predict.purity.rust,Woda z Górnego poziomu
|
||||
nightlog.predict.win,"Trafna predykcja: „{0}”, wypłacono {1}."
|
||||
nightlog.predict.lose,"Błędna predykcja: „{0}”, utracono stawkę {1}."
|
||||
nightlog.predict.void,"Predykcja unieważniona: „{0}”, zwrócono stawkę {1}."
|
||||
nightlog.predict.caught,"Wykryto transakcję poufną: „{0}”, skonfiskowano stawkę i wygraną w kwocie {1}, odnotowano oszustwo."
|
||||
predict.tab.markets,Rynki
|
||||
predict.tab.intel,Informacje
|
||||
predict.acct.crt,{0}: CRT {1}
|
||||
predict.tier.0,niski
|
||||
predict.tier.1,średni
|
||||
predict.tier.2,wysoki
|
||||
predict.clue.tip,"Cynk ({0}): donosi, że {1}"
|
||||
predict.clue.queued,Zaplanowano: start w dniu {0}
|
||||
predict.clue.queued2,Zaplanowano: dzień {0} „{1}”
|
||||
predict.clue.cool,Wydarzenie aktywne lub w trakcie odnowienia
|
||||
predict.clue.busy,Operacja frakcji w toku; brak nowych w najbliższym czasie
|
||||
predict.clue.halving,Halving w dniu {0}; kotwica rośnie tydzień wcześniej
|
||||
predict.clue.anchor,Kotwica cenowa wynosi obecnie {0}
|
||||
predict.clue.gas,Gas z ostatnich dni: {0}
|
||||
predict.clue.drain,Zużycie na noc: {0}
|
||||
predict.clue.era,"Losowo w dniach {0}–{1}, zapowiedź z wyprzedzeniem"
|
||||
predict.clue.era.warned,Zapowiedziano: start w dniach {0}–{1}
|
||||
predict.q.gas,{0}: wskaźnik gas >= {1}
|
||||
predict.q.cra,{0}: wydano ostrzeżenie CRA
|
||||
predict.q.era,{0}: początek ery koparek
|
||||
predict.era,Era koparek
|
||||
predict.pos3,Śr. {0} teraz {1}
|
||||
predict.pos4,Sprzedaż teraz zwróci {0}
|
||||
intel.h,Handlarz informacjami
|
||||
intel.locked,Wymaga sklepu Web3 i reputacji na Czarnym Rynku {0}.
|
||||
intel.brief.buy,Kup raport sytuacyjny ({0} CRT)
|
||||
intel.brief.none,Nie zakupiono jeszcze raportu.
|
||||
intel.brief.day,Raport z dnia {0}
|
||||
intel.tips.h,Informacje poufne
|
||||
intel.tips.none,Brak tematów do zapytań (tylko operacje frakcji i era koparek).
|
||||
intel.tip.buy,Dokładność ok. {0}% {1} CRT
|
||||
intel.err.funds,Niewystarczająca ilość CRT w portfelu lub rynek nie jest już dostępny.
|
||||
intel.brief.sum,"Raport sytuacyjny, {0} CRT"
|
||||
intel.tip.sum,Informacja poufna {0} CRT: {1}
|
||||
intel.brief.done,Otrzymano raport sytuacyjny.
|
||||
intel.tip.done,Mówią: {0}.
|
||||
predict.brief.levels,Ochrona {0} Rew. {1} Czarny Rynek {2} Niepokoje {3} Górny poz. {4}
|
||||
predict.brief.busy,{0}: operacja w toku
|
||||
predict.brief.queued,{0}: operacja zaplanowana
|
||||
predict.brief.none,{0}: brak operacji do rozpoczęcia
|
||||
predict.brief.can,{0}: można rozpocząć {1}
|
||||
predict.clue.push,Przesunięcie ceny o {0}%: wysokie ryzyko
|
||||
nightlog.predict.manip,"Predykcja uznana za manipulację rynkową: „{0}”, skonfiskowano stawkę {1}, odnotowano oszustwo."
|
||||
news.manip.title,Giełda bada nietypowe transakcje
|
||||
news.manip.desc,"Organy regulacyjne donoszą, że za pomocą dużych zleceń spot manipulowano ceną, by czerpać zyski z instrumentów pochodnych i predykcji; środki przejęto."
|
||||
perp.manip,Zysk z zamknięcia w kwocie {0} uznano za manipulację rynkową i skonfiskowano; konto kontraktów wieczystych zamrożone na {1} dni.
|
||||
web3.sub.ponzi,Lokaty
|
||||
ponzi.h,Piramida finansowa
|
||||
ponzi.acct,Portfel emitenta {0}: CRC {1}
|
||||
ponzi.rate,Stawka dzienna: {0}%
|
||||
ponzi.pool,Pula {0} / limit {1}
|
||||
ponzi.inflow,Nowe wpłaty z ostatniej nocy: {0}
|
||||
ponzi.interest,Odsetki należne dziś w nocy: {0}
|
||||
ponzi.own,Odsetki opłacone z własnej kieszeni: {0}
|
||||
ponzi.wind,Ryzyko zgłoszenia: {0}
|
||||
ponzi.wind.low,niskie
|
||||
ponzi.wind.mid,średnie
|
||||
ponzi.wind.high,wysokie
|
||||
ponzi.idle,Brak wyemitowanej piramidy.
|
||||
ponzi.done,Piramida została zamknięta; tylko jedna na zapis gry.
|
||||
ponzi.ops,Działania
|
||||
ponzi.rug,Rug pull puli ({0})
|
||||
ponzi.rug.confirm,"Kliknij ponownie, aby potwierdzić rug pull {0}"
|
||||
ponzi.rugged,"Przejęto {0}, całkowicie skażone."
|
||||
ponzi.open,Załóż piramidę
|
||||
ponzi.ad,Koszt marketingu {0} CRC z bieżącego portfela; wymagany podpis.
|
||||
ponzi.start,Uruchom
|
||||
ponzi.started,Uruchomiono.
|
||||
ponzi.err,Niewystarczająca ilość CRC w portfelu na pokrycie kosztów marketingu.
|
||||
nightlog.ponzi.collapse,"Piramida nie mogła wypłacić odsetek; nastąpił szturm na pulę, skonfiskowano {0}, odnotowano oszustwo, a reputacja na Dolnym poziomie została wyzerowana."
|
||||
nightlog.ponzi.reported,"Piramida została zgłoszona; skonfiskowano pulę {0}, odnotowano oszustwo, a reputacja na Dolnym poziomie została wyzerowana."
|
||||
news.ponzi.title,Upadek piramidy finansowej
|
||||
news.ponzi.desc,"Zgłoszono piramidę finansową działającą na Dolnym poziomie; wściekli inwestorzy oblegli lokal, a organy regulacyjne zamroziły środki."
|
||||
news.ponzi.rug.title,Oszustwo inwestycyjne
|
||||
news.ponzi.rug.desc,Twórca piramidy finansowej uciekł ze wszystkimi środkami; inwestorzy z Dolnego poziomu stracili wszystko.
|
||||
ponzi.start.sum,"Uruchomienie piramidy finansowej, stawka dzienna {0}%, marketing {1} CRC"
|
||||
ponzi.rug.sum,Rug pull puli {0}
|
||||
ponzi.err.wallet,Podpisz portfelem emitenta.
|
||||
predict.clue.counter,"Informacje: zaplanowane (informator przy ladzie, notatka z plotką)"
|
||||
web3.sub.airdrop,Airdropy
|
||||
air.h,Airdropy
|
||||
air.none,Brak airdropów do odebrania.
|
||||
air.row,{0} nagroda {1} CRC {2} do dnia {3}
|
||||
air.claim,Odbierz
|
||||
air.unlimited,autoryzacja {0} bez limitu
|
||||
air.limited,autoryzacja {0} {1}
|
||||
air.approvals,Autoryzacje: {0}
|
||||
air.approvals.none,Brak autoryzacji.
|
||||
air.approval,{0}: {1}
|
||||
air.revoke,Cofnij
|
||||
air.sum,Odbiór airdropa {0} ({1})
|
||||
air.claimed,Otrzymano {0} CRC.
|
||||
air.auth,Autoryzuj portfel
|
||||
air.unauth,Brak autoryzacji
|
||||
air.authed,Autoryzowano: {0}
|
||||
air.authed.msg,Portfel autoryzowany dla {0}.
|
||||
air.auth.sum,Autoryzuj {0} do działania w imieniu tego portfela. Zakres: {1}.
|
||||
air.err.unauth,Najpierw autoryzuj portfel dla tego airdropu.
|
||||
air.revoke.sum,Cofnięcie autoryzacji {1} dla {0}
|
||||
air.revoked,Autoryzację cofnięto.
|
||||
air.err.wallet,Podpisz portfelem autoryzującym.
|
||||
pool.h,Zewnętrzne pule zysków (CRC)
|
||||
pool.none,Obecnie brak.
|
||||
pool.col.name,Pula
|
||||
pool.col.rate,Dziennie
|
||||
pool.col.reserve,Rezerwa
|
||||
pool.col.lock,Blokada
|
||||
pool.col.audit,Audyt
|
||||
pool.col.mine,Moje
|
||||
pool.yes,tak
|
||||
pool.no,nie
|
||||
pool.pending,wypłacanie
|
||||
pool.closed,(zamknięta)
|
||||
pool.deposit,Wpłata
|
||||
pool.withdraw,Wypłata
|
||||
pool.withdraw.lock,Wniosek o wypłatę (dni: {0})
|
||||
pool.err.cap,Przekroczono limit puli; pozostało: {0}.
|
||||
pool.err.none,Brak depozytu.
|
||||
pool.sum.in,Wpłata do {0}: {1} CRC
|
||||
pool.sum.out,Wypłata {1} CRC z {0}
|
||||
pool.done.in,Wpłacono {0} CRC do {1}.
|
||||
pool.done.out,Wypłacono {0} CRC.
|
||||
pool.done.lock,"Zgłoszono {0} CRC, wpłynie w dniu {1}."
|
||||
nightlog.scam.drain,{1} {2} w {0} zostało pobrane przez „{3}” za pomocą autoryzacji.
|
||||
nightlog.scam.rug,Pula zysków „{0}” przeprowadziła rug pull; {1} CRC z {2} przepadło.
|
||||
nightlog.scam.dry,Pula zysków „{0}” wyczerpała rezerwy i została zamknięta; {1} CRC zwrócono do {2}.
|
||||
nightlog.scam.paid,Wypłata z „{0}” dotarła: {2} otrzymał {1} CRC.
|
||||
nightlog.scam.fakepay,Sfałszowany przelew: {0}
|
||||
nightlog.scam.sent,{0} {1} wysłane na bezpieczny adres „wsparcia” trafiło do oszusta.
|
||||
coinpay.intro,Zapłacę w {0}; potwierdzenie w łańcuchu zajmie chwilę.
|
||||
coinpay.intro.fake,"Już wysłałem {0}, oto zrzut ekranu. Dawaj towar, spieszę się."
|
||||
coinpay.fake.entry,"{0} zabrał {1}, twierdząc, że zapłacił {2} kredytów w monetach; brak transakcji w łańcuchu."
|
||||
scam.support.name,Wsparcie Poinbase
|
||||
scam.support.1,"Dzień dobry, tutaj wsparcie Poinbase. Wykryliśmy nietypowe logowanie na twoim koncie i zostało ono oznaczone."
|
||||
scam.support.2,Prześlij dzisiaj {0} CRC na bezpieczny adres {1} w celu weryfikacji; zostaną zwrócone zaraz potem.
|
||||
scam.support.3,"W przeciwnym razie konto zostanie trwale zamrożone. Muszę lecieć, pamiętaj o przelewie."
|
||||
predict.sold.caught,"Wykryto transakcje poufne przy sprzedaży: stawka i zysk skonfiskowane, oszustwo w kartotece."
|
||||
predict.row.move," (ubiegłej nocy {0} {1})"
|
||||
predict.stats.h,Historia (śr. cena otwarcia / wskaźnik rzeczywisty)
|
||||
predict.stats.row,"{0}: rynki: {1}, śr. otwarcie {2}, wystąpienie: {3}%"
|
||||
predict.kind.Event,Wydarzenia prasowe
|
||||
predict.kind.Faction,Operacje frakcji
|
||||
predict.kind.Purity,Czystość wody
|
||||
predict.kind.Price,Cena PSC
|
||||
predict.kind.Gas,Gas
|
||||
predict.kind.Cra,Ostrzeżenie CRA
|
||||
predict.kind.Era,Era koparek
|
||||
nightlog.predict.move,Predykcja „{0}”: zmiana {1} -> {2}
|
||||
nightlog.predict.why," ({0})"
|
||||
chart.empty,Wykres dzienny {0}: brak historii; zapis od dzisiaj.
|
||||
chart.caption,{0} dzienny Maks {2} Min {3} Zamk {4} ({5}%)
|
||||
chart.legend,"<size=80%>zielony: wzrost, czerwony: spadek; żółta 7-dniowa MA; słupki: szary rynek / błękitny gracz</size>"
|
||||
chart.legend.thr,"<size=80%>zielony: wzrost, czerwony: spadek; żółta 7-dniowa MA; niebieska przerywana: próg</size>"
|
||||
news.story.serpico_rev.title,Rewolucja ma haki na Ochronę
|
||||
news.story.serpico_rev.desc,"Rewolucja rzekomo zdobyła dowody korupcji wewnątrz Ochrony. Wieści z puli stakingu: pokaźna suma zasiliła rezerwę Rewolucji, a kurs SPARK się umacnia."
|
||||
news.story.serpico_bm.title,Czarny Rynek zawiera ciche porozumienie
|
||||
news.story.serpico_bm.desc,"Wewnętrzny dokument Ochrony zmienił właściciela na Czarnym Rynku. Od tamtej pory rozliczenia w Darknecie są zauważalnie stabilniejsze, a realizacja CRT ani razu nie zawiodła."
|
||||
news.story.serpico_sec.title,Ochrona rozpoczyna wewnętrzną czystkę
|
||||
news.story.serpico_sec.desc,"Ochrona zapowiedziała pełne śledztwo w sprawie wewnętrznej korupcji i zaostrzenie monitorowania przepływów finansowych. Poinbase zaostrza kontrolę wypłat, a miksery zostały wymienione z nazwy."
|
||||
news.story.eleanor_leak.title,Wyciek danych o hodowli nutriowoców
|
||||
news.story.eleanor_leak.desc,"Gazeta z Dolnego poziomu opublikowała badania pozwalające nutriowocom na ponowne wytwarzanie nasion; akcje Pastelle runęły. Bank powierniczy przechowujący fundusze Górnego poziomu zgłasza złe długi, a Rewolucja rośnie w siłę."
|
||||
news.story.eleanor_return.title,Pastelle odzyskuje skradzione dane
|
||||
news.story.eleanor_return.desc,"Pastelle potwierdziło odzyskanie skradzionych danych badawczych. Kapitał z Górnego poziomu odetchnął z ulgą, a rating banku powierniczego CRC został podniesiony."
|
||||
news.story.lun_arrested.title,Oficer Lun aresztowany za nadużycie władzy
|
||||
news.story.lun_arrested.desc,Ochrona aresztowała na miejscu Oficera Luna za nadużycie władzy i zapowiedziała bezwzględną walkę z nielegalnym handlem przez najbliższe dwa tygodnie.
|
||||
tumbler.name,Tumbler
|
||||
tumbler.v1.1,"Cześć. Słyszałem, że tutejszy terminal jest połączony z moim mikserem."
|
||||
tumbler.v1.2,Sam to napisałem. Mówią na mnie Tumbler.
|
||||
tumbler.v1.3,Nie dotyka twojego towaru ani nie prowadzi ksiąg. Po prostu miesza monety.
|
||||
tumbler.v1.4,"Przechodziłem obok. Chciałem zobaczyć, jak wyglądają moi użytkownicy."
|
||||
tumbler.v2.1,Robi się nieciekawie. Ochrona bierze się za usługi mikserów w łańcuchu.
|
||||
tumbler.v2.2,Oznaczyli kilka dużych adresów i doszli po nitce do mojego węzła.
|
||||
tumbler.v2.3,"Jeśli mikser padnie na kilka dni, nie panikuj. Monety w środku nie przepadną."
|
||||
tumbler.v3.1,"Zamknęli mój węzeł. Prędzej czy później dowiedzą się, gdzie mieszkam."
|
||||
tumbler.v3.2,"Mam dysk z kluczami, są na nim klucze podpisujące miksera."
|
||||
tumbler.v3.3,"Jeśli wpadnie w ręce Ochrony, będą mogli odtworzyć historię każdego użytkownika. Twoją też."
|
||||
tumbler.v3.ask,Możesz to schować na kilka dni?
|
||||
tumbler.v3.choice.hide,[Weź dysk i schowaj go]
|
||||
tumbler.v3.choice.report,"[Zgódź się, a potem zawiadom Ochronę]"
|
||||
tumbler.v3.choice.sell,[Weź dysk i sprzedaj go na Czarnym Rynku]
|
||||
tumbler.v3.thanks1,Dzięki. Wrócę po niego za kilka dni.
|
||||
tumbler.v3.thanks2,"Nie zostawiaj go na wierzchu. Jeśli znajdą go podczas przeszukania, obaj mamy przerąbane."
|
||||
tumbler.v3.report1,...W porządku. Wpadnę później.
|
||||
tumbler.v4.back.1,Przyszedłem po dysk.
|
||||
tumbler.v4.back.2,Węzeł został przeniesiony w nowe miejsce. Ochrona prędko go nie znajdzie.
|
||||
tumbler.v4.back.3,To w podziękowaniu za kłopot. Od teraz masz prowizję miksera za pół ceny.
|
||||
tumbler.v4.lost.1,Gdzie jest dysk?
|
||||
tumbler.v4.lost.2,...Zgubiłeś go?
|
||||
tumbler.v4.lost.3,Nieważne. Coś wymyślę.
|
||||
tumbler.v4.sold.1,"Sprzedałeś dysk na Czarnym Rynku, co?"
|
||||
tumbler.v4.sold.2,"Teraz oni zarządzają mikserem. Prowizje wzrosły dwukrotnie, a pieniądze użytkowników mogą zniknąć w każdej chwili."
|
||||
tumbler.v4.sold.3,Zapamiętam to sobie.
|
||||
tumbler.v4.none.1,Nieważne. Nigdy mnie tu nie było.
|
||||
item.keydrive.name,Dysk z kluczami
|
||||
item.keydrive.desc,"Nośnik danych powierzony ci przez Tumblera, zawierający klucze podpisujące miksera. Kontrabanda: jeśli zostanie znaleziony podczas przeszukania, trafi do twojej kartoteki."
|
||||
mixer.closed,Mikser został wyłączony i nie przyjmuje nowych wpłat. Monety znajdujące się w środku wrócą normalnie.
|
||||
news.tumbler.sanction.title,Ochrona zajmuje węzeł miksera
|
||||
news.tumbler.sanction.desc,"Ochrona ogłosiła zajęcie węzła usługi miksera on-chain, twierdząc, że ułatwiał on pranie pieniędzy. Usługa jest tymczasowo niedostępna."
|
||||
news.tumbler.caught.title,Operator miksera aresztowany
|
||||
news.tumbler.caught.desc,"Operator miksera znany jako Tumbler został aresztowany na Dolnym poziomie. Ochrona podaje, że usługa miksera została trwale zamknięta."
|
||||
news.tumbler.sold.title,Usługa miksera zmienia właściciela
|
||||
news.tumbler.sold.desc,"Krążą słuchy, że klucze do podpisywania usługi miksera z Dolnego poziomu trafiły w ręce Czarnego Rynku, a opłaty natychmiast wzrosły. Użytkownicy obawiają się o swoje środki."
|
||||
nightlog.tumbler.gift,Tumbler odebrał dysk z kluczem i w podziękowaniu zostawił {0} CRT (wysłano na {1}); opłaty miksera zmniejszono o połowę.
|
||||
mixer.status.closed,Status: wyłączony
|
||||
yield.sub.pools,Pule zysku
|
||||
yield.sub.mine,Emisja piramidy
|
||||
pool.side.h,Wpłata
|
||||
ponzi.early,Piramidy finansowe można tworzyć od dnia {0}.
|
||||
bpay.h,Płatność
|
||||
bpay.qty,Ilość
|
||||
bpay.total,Razem (kredyty): {0}
|
||||
bpay.need,Do zapłaty: {0} {1} saldo portfela: {2}
|
||||
bpay.invoice,Utwórz rachunek
|
||||
bpay.swap.h,Autokonwersja na {0}
|
||||
bpay.swap.none,Żadna inna moneta w portfelu nie wystarcza
|
||||
bpay.swap.need,"Do zapłaty: {0} {1}, w tym {2}% poślizgu"
|
||||
bpay.swap.btn,Konwertuj i zapłać
|
||||
bpay.swap.sum,"{0}: autokonwersja, zapłać {2} {1}, wymiana na {3} przed złożeniem zamówienia"
|
||||
bpay.back,Powrót
|
||||
cart.fab,Koszyk {0}
|
||||
cart.h,Koszyk
|
||||
cart.empty,Koszyk jest pusty.
|
||||
cart.added,Dodano do koszyka: {0}
|
||||
cart.back,Powrót do sklepu
|
||||
cart.done,Opłacono: {0} szt.
|
||||
cart.partial,Opłacono: {0} szt.; nieudane: {1} szt. (brak zapasów lub salda).
|
||||
black.info.accepts,Akceptuje: {0}
|
||||
black.info.advance.yes,akceptowana wypłata zaliczkowa
|
||||
black.info.advance.no,brak wypłaty zaliczkowej
|
||||
settings.section.ui,Interfejs
|
||||
settings.section.story,Fabuła
|
||||
settings.section.difficulty,Poziom trudności
|
||||
settings.terminal_size,Rozmiar terminala handlowego
|
||||
settings.terminal_size_desc,Rozmiar okna w jednostkach interfejsu (szerokość × wysokość). Obowiązuje po następnym otwarciu terminala.
|
||||
settings.tumbler_story,Wątek Tumblera
|
||||
settings.tumbler_story_desc,Wizyty Tumblera i zlecenie z dyskiem kluczy. Po wyłączeniu nie będzie nowych wizyt; dotychczasowy postęp zostaje.
|
||||
settings.risk_scale,Mnożnik ryzyka
|
||||
settings.risk_scale_desc,"Mnoży szanse na oszustwa, rug pulle, zatrucie portfela, podmianę adresu i phishing. Dotyczy wszystkich zapisów."
|
||||
settings.mining_scale,Mnożnik wydobycia
|
||||
settings.mining_scale_desc,Mnoży nagrodę za blok wypłacaną koparkom. Dotyczy wszystkich zapisów.
|
||||
gg.header,Komisja Handlu Stacji
|
||||
gg.p1.cap,Karta graficzna
|
||||
gg.p1.makers,"Na stacji działa dwóch popularnych producentów:\n\n - Probidia (""PB"")\n - PMD (""MD"")"
|
||||
gg.p1.note,"Niezależnie od producenta wartość karty zależy tylko od ceny katalogowej prawdziwego chipa i jego kondycji: przy pełnej kondycji równa się cenie katalogowej, przy kondycji 0 zostaje tylko {CardValueFloor:%}."
|
||||
gg.fan.h,Łopatki
|
||||
gg.fan.0,Czyste (cena bez zmian)
|
||||
gg.fan.1,Zakurzone (-{CardFanDust:%})
|
||||
gg.fan.2,Wyszczerbione (-{CardFanChipped:%})
|
||||
gg.fin.h,Styki
|
||||
gg.fin.0,Błyszczące (cena bez zmian)
|
||||
gg.fin.1,Zmatowiałe (-{CardFingersDark:%})
|
||||
gg.fin.2,Utlenione (-{CardFingersOxidized:%})
|
||||
gg.brk.h,Zaślepka
|
||||
gg.brk.0,Nienaruszona (cena bez zmian)
|
||||
gg.brk.1,Porysowana (-{CardBracketScratch:%})
|
||||
gg.seal.h,Plomba
|
||||
gg.seal.0,Nienaruszona (cena bez zmian)
|
||||
gg.seal.2,Brak (-{CardSealMissing:%})
|
||||
gg.wear.note,"Łopatki, styki i zaślepka pogarszają się przez nocne zużycie i nigdy się nie poprawiają; plomba jest cechą stałą. Stan wpływa też na moc obliczeniową, zużycie i szansę przepalenia."
|
||||
gg.serial.h,Numer seryjny
|
||||
gg.serial.cap,Tył karty (naklejka z numerem)
|
||||
gg.serial.pb,"Probidia (""PB"")\n Prawidłowe kody fabryk: 11, 12, 21, 34, 47"
|
||||
gg.serial.md,"PMD (""MD"")\n Prawidłowe kody fabryk: 13, 22, 35, 41, 58"
|
||||
gg.print.h,Nadruk z tyłu
|
||||
gg.print.0,Zgodny z modelem
|
||||
gg.print.1,Inny model (podróbka)
|
||||
gg.print.2,"Przedruk, krzywy (podróbka)"
|
||||
gg.point.h,Wskazywanie
|
||||
gg.ex.card,"Przykład: {0}, kondycja {1}%"
|
||||
gg.ex.base,Wartość bazowa: +{0}
|
||||
gg.ex.fan,Wyszczerbione łopatki: -{0}
|
||||
gg.ex.fin,Zmatowiałe styki: -{0}
|
||||
gg.ex.seal,Brak plomby: -{0}
|
||||
gg.ex.total,Wartość końcowa: {0}
|
||||
gg.ex.note,Każda obniżka to część wartości bazowej; obniżki sumuje się i odejmuje.
|
||||
gg.ex.fan1,Zakurzone łopatki: -{0}
|
||||
gg.ex.fin2,Utlenione styki: -{0}
|
||||
gg.ex.brk,Porysowana zaślepka: -{0}
|
||||
gg.ex.nodisc,Brak obniżek: -0
|
||||
gg.ex.fake,"Deklarowano {0}, faktycznie {1}: wycena wg faktycznego chipa"
|
||||
gg.ex.claimed,Cena dla podanego modelu: {0}
|
||||
gg.ex.gap,Różnica względem oferty: {0}
|
||||
gg.ex.h2,Przykład oceny: podróbka
|
||||
gg.ex.h3,Przykład oceny: mocno zużyta
|
||||
gg.ex.h4,Przykład oceny: lekko używana
|
||||
gg.ex.h5,Przykład oceny: nowa
|
||||
lbl.price,Cena z etykiety: {0}
|
||||
lbl.row.count,Wentylatory
|
||||
lbl.row.pin,Zasilanie
|
||||
lbl.count.1,1 wentylator
|
||||
lbl.count.2,2 wentylatory
|
||||
lbl.count.3,3 wentylatory
|
||||
lbl.pin.0,6-pin
|
||||
lbl.pin.1,8-pin
|
||||
lbl.pin.2,2× 8-pin
|
||||
gg.p1.body,"Karty graficzne to podstawowy element każdej koparki i towar najczęściej podrabiany na rynku wtórnym.\nO autentyczności karty świadczą cztery cechy: liczba wentylatorów, złącze zasilania, nadruk z tyłu i numer seryjny. Autentyczna jest tylko karta zgodna z deklarowanym modelem pod każdym z tych czterech względów; jedna rozbieżność oznacza podróbkę.\nWartość karty zależy od modelu prawdziwego układu i jego kondycji, a każdy ślad zużycia obniża cenę.\n\nTen poradnik zawiera całą wiedzę potrzebną do wyceny karty graficznej."
|
||||
gg.p2.h,Modele kart
|
||||
gg.p2.body,Model określa liczbę wentylatorów i złącze zasilania. Podróbka to układ niższego modelu w obudowie wyższego; jej wydajność i wartość wynikają z prawdziwego układu w środku.
|
||||
gg.tier.0,"RTX 60 / RX 70: 6-pin, 1 went."
|
||||
gg.tier.1,"RTX 70 / RX 80: 8-pin, 2 went."
|
||||
gg.tier.2,"RTX 80 / RX 800: 8-pin, 3 went."
|
||||
gg.tier.3,"RTX 90 / RX 900: 2× 8-pin, 3 went."
|
||||
gg.count.h,Liczba wentylatorów
|
||||
gg.count.body,"Model określa liczbę wentylatorów: jeden w RTX 60 i RX 70, dwa w RTX 70 i RX 80, trzy w RTX 80, RTX 90, RX 800 i RX 900.\nLiczba wentylatorów niezgodna z deklarowanym modelem oznacza podróbkę."
|
||||
gg.pin.h,Złącze zasilania
|
||||
gg.pin.body,"Złącze zasilania również zależy od modelu: 6-pin w RTX 60 i RX 70, 8-pin w RTX 70, RTX 80, RX 80 i RX 800, 2× 8-pin w RTX 90 i RX 900.\nZłącze zasilania niezgodne z deklarowanym modelem oznacza podróbkę."
|
||||
gg.serial.body,"Numer seryjny znajduje się na naklejce z tyłu karty w formacie: prefiks, kod modelu, myślnik, dwucyfrowy kod fabryki, myślnik i czterocyfrowy numer kolejny, na przykład PB2-21-6251."
|
||||
gg.serial.rule,"Kody modelu od 1 do 4 odpowiadają kolejno RTX 60 / RX 70, RTX 70 / RX 80, RTX 80 / RX 800 i RTX 90 / RX 900.\nKod modelu niezgodny z modelem (naklejka pochodzi z oryginalnego układu) albo nieprawidłowy kod fabryki lub długość (naklejka dodana później) oznacza podróbkę. Kod fabryki służy wyłącznie do sprawdzania autentyczności i nie wpływa na cenę."
|
||||
gg.print.note,"Karta jest autentyczna tylko wtedy, gdy liczba wentylatorów, złącze zasilania, nadruk i numer seryjny są zgodne z modelem. Podróbka ma rozbieżność w co najmniej jednym punkcie, ale pozostałe może imitować poprawnie, dlatego trzeba sprawdzić każdy z nich."
|
||||
gg.point.body,"Kartę sprawdza się lupą. Na pasku etykiet tylko wiersz modelu ma przycisk „Wskaż model”; cztery wiersze pod nim (wentylatory, zasilanie, nadruk z tyłu, numer seryjny) są tylko do odczytu, a każdy z czterech wierszy stanu — łopatki, styki, śledź, plomba — ma własny przycisk „Wskaż”.\nWskazanie ukrytego problemu ze stanem zmienia ten wiersz na stan rzeczywisty, a cena spada o różnicę; wskazanie czegoś prawdziwego druga strona odrzuca, a reputacja na tym traci.\nJeśli liczba wentylatorów, zasilanie, nadruk z tyłu lub numer seryjny nie zgadza się z podanym modelem, wskaż model: karta zostaje uznana za podróbkę, model wraca do prawdziwego układu, a cena jest liczona od nowa dla tego układu.\n\nKarty przynoszone przez klientów gildii rzeczoznawców działają tak samo: po wskazaniu problemów wycena się zmienia, aż zostanie podana prawidłowa wartość."
|
||||
gg.ex.serial,Numer seryjny: {0}
|
||||
gg.ex.h,"Przykład wyceny: wyszczerbiona łopatka, zmatowiałe styki, brak plomby"
|
||||
rig.label.status,Stan
|
||||
rig.st.cards,Karty
|
||||
rig.st.power,Pobór
|
||||
rig.st.hash,Moc obl.
|
||||
rig.st.kj,{0} kJ/dzień
|
||||
lbl.point.model,Wskaż model
|
||||
col.crcprice,Cena w CRC
|
||||
swap.pay,Płacę
|
||||
swap.get,Otrzymuję
|
||||
swap.preview,"Około {0} {1} pule: {2}, strata {3}%"
|
||||
swap.go,Wymień
|
||||
swap.same,Monety płatności i odbioru muszą się różnić.
|
||||
mint.need,Wymaga {0} CRC i {1} SPARK
|
||||
mint.reserve,Pokrycie rezerwy {0}% Zabezpieczenie {1}%
|
||||
mint.queue,Oczekujące zlecenia
|
||||
mint.order,"{0} {1} CRA, dzień {2}"
|
||||
stake.coin,Moneta wpłaty
|
||||
stake.sum.via,Wymień {0} {1} → około {2} CRA i stakuj
|
||||
nightlog.cra.lost,Emitent nie odpowiedział: zlecenie ({1}) na {0} CRA przepadło.
|
||||
news.crawarn.desc,"Ktoś liczy rezerwę Rewolucji i zastakowane CRA mogą nie zostać w pełni wypłacone. Odblokowanie trwa cztery dni; niektórzy mówią, że czas działać."
|
||||
news.cralow.desc,"Pokrycie rezerwy maleje, a Rewolucja obniżyła stawkę stakingu CRA do ułamka."
|
||||
poin.sub.funds,Środki
|
||||
funds.receive,Wpłata
|
||||
funds.send,Wypłata
|
||||
funds.bank,Konto bankowe
|
||||
funds.wallet,Portfel
|
||||
funds.to,Adres odbiorcy
|
||||
funds.go,Wyślij
|
||||
funds.sending,Wysyłanie {0} {1} na {2}
|
||||
funds.confirm,Potwierdzenie {0}/{1}
|
||||
funds.done,{0} {1} dotarło do {2}.
|
||||
funds.done.void,"Wysłano {0} {1}; adres nie ma właściciela, monety przepadły."
|
||||
funds.err.addr,Nieprawidłowy adres.
|
||||
funds.err.self,To adres wpłat Poinbase.
|
||||
funds.err.known,Ten adres przyjmuje tylko płatności za rachunek.
|
||||
funds.err.fee,Kwota nie pokrywa opłaty gas.
|
||||
wallets.sub.explorer,Eksplorator
|
||||
explorer.search,Adres
|
||||
explorer.all,Najnowsze
|
||||
explorer.none,Brak przelewów.
|
||||
explorer.col.block,Blok
|
||||
explorer.col.amount,Kwota
|
||||
explorer.mixer,Mikser
|
||||
cra.mint,Wybij
|
||||
cra.burn,Spal
|
||||
mint.h,Oficjalne wybijanie (CRC + SPARK)
|
||||
mint.sum.in,Wybij {0} CRA za {1} CRC i {2} SPARK ({3}–{4} dni)
|
||||
mint.sum.out,Spal {0} CRA na CRC i SPARK ({1} dni)
|
||||
mint.done.in,Zlecenie wybicia złożone; termin: dzień {0}.
|
||||
mint.done.out,Zlecenie spalenia złożone; termin: dzień {0}.
|
||||
nightlog.cra.minted,Wybito {0} CRA i zastakowano ({1}).
|
||||
nightlog.cra.burned,"Spalono {0} CRA: +{1} CRC, +{2} SPARK ({3})."
|
||||
predict.clue.subsidy,Rezerwa: {0}%; przy zerze ostrzeżenie jest pewne
|
||||
air.noapprove,bez zgody na tokeny
|
||||
tab.gray,Szara sieć
|
||||
wallets.sub.list,Lista
|
||||
entry.web3.l1,Handel zdecentralizowany i zyski
|
||||
entry.mining.l1,Stan koparek i nocne zyski
|
||||
entry.gray.l1,Mikser i sklep
|
||||
entry.wallets.l1,Portfele sprzętowe i eksplorator
|
||||
entry.wallets.l2,Portfele {0} / {1}
|
||||
black.sell.add,Dodaj oferty
|
||||
black.sell.back,Wróć do witryny
|
||||
black.sell.kinds,Wystawiono {0}/{1} rodzajów
|
||||
black.sell.have,Wystawiono: {0}
|
||||
black.sell.coins,Akceptowane monety
|
||||
black.sell.off,Zdejmij
|
||||
black.sell.off.n,Zdejmij ×{0}
|
||||
black.sell.nocoin,Wymagana co najmniej jedna akceptowana moneta.
|
||||
black.sell.empty,Brak wystawionych towarów.
|
||||
black.sell.delisted,Zdjęto {0}; towar wrócił do magazynu.
|
||||
black.sell.partial,"Wystawiono {0}, nie udało się wystawić {1}."
|
||||
black.sell.limit.stack,Maksymalnie {0} sztuk każdego towaru.
|
||||
black.sell.limit.kinds,Jednocześnie można wystawić maksymalnie {0} rodzajów.
|
||||
shelf.fab,Półka {0}
|
||||
delist.fab,Potwierdź zdjęcie {0}
|
||||
black.fee.h,Gotowe do wystawienia
|
||||
black.fee.line,{0} ×{1} · cena {2} ({3})
|
||||
black.fee.total,Opłata za wystawienie {0}
|
||||
black.fee.sum,Opłata za wystawienie ({0} szt.)
|
||||
black.sale.Sold,"sprzedane, wypłata w dniu {0} w {1}"
|
||||
explorer.col.day,Dzień
|
||||
explorer.day,Dzień {0}
|
||||
explorer.pool,pula RatDigg
|
||||
explorer.desk,kantor Ponero
|
||||
black.fee.pay,Zapłać opłatę za wystawienie
|
||||
explorer.col.from,Od
|
||||
explorer.col.to,Do
|
||||
rig.st.cond,Kondycja
|
||||
asic.st.dead,Przepalony
|
||||
perp.preview,Wartość nominalna {0} szac. śr. cena {1} (poślizg {2}%)
|
||||
perp.sim.close,Zamknięcie wartość nominalna {0} szac. śr. cena {1} (poślizg {2}%)
|
||||
perp.sim.close2,Opłata {0} zwrot ok. {1} CRC (zysk/strata {2})
|
||||
trade.sim.sell,Sprzedaż da ok. {0} {1} śr. {2} poślizg {3}%
|
||||
trade.sim.buy,Zakup kosztuje ok. {0} {1} śr. {2} poślizg {3}%
|
||||
trade.amount.unit,Ilość ({0})
|
||||
trade.fee,Prowizja {0}%
|
||||
trade.sim.thin,Przekracza płynność puli
|
||||
news.wipe.down.title,"{0} spada o {1}% w jeden dzień, {2} traderów zlikwidowanych"
|
||||
news.wipe.down.desc,"W ciągu ostatniego dnia zlikwidowano {1} długich pozycji na kontraktach perp {0}, łącznie {2} kredytów. Fundusz ubezpieczeniowy Poinbase wynosi {3} kredytów."
|
||||
news.wipe.up.title,"{0} rośnie o {1}% w jeden dzień, {2} traderów zlikwidowanych"
|
||||
news.wipe.up.desc,"W ciągu ostatniego dnia zlikwidowano {1} krótkich pozycji na kontraktach perp {0}, łącznie {2} kredytów. Fundusz ubezpieczeniowy Poinbase wynosi {3} kredytów."
|
||||
hot.name,Sprzedawca
|
||||
hot.intro.CRT,"Ostatnio jest gorąco, a te CRT parzą w ręce. Potrzebuję gotówki, szybko."
|
||||
hot.intro.PSC,Portfel pewnej kopalni zmienił wczoraj właściciela. PSC jest teraz u mnie i biorę tylko gotówkę.
|
||||
hot.intro.PONERO,"Okup, w Ponero. Nikt tego nie wyśledzi. Tylko gotówka."
|
||||
hot.offer,"{0} {1}, warte {2} po dzisiejszym kursie. Daj mi {3} w gotówce, a monety są twoje od razu."
|
||||
hot.choice.yes,Przyjmij
|
||||
hot.choice.no,Odmów
|
||||
hot.say.yes,Umowa stoi.
|
||||
hot.say.no,Nie tknę tego.
|
||||
hot.done,Monety wysłane. Nigdy się nie spotkaliśmy.
|
||||
hot.refused,Inni chętnie wezmą.
|
||||
hot.nocash,Nie masz nawet gotówki? Daj spokój.
|
||||
hot.nowallet,"Brak podłączonego portfela, gdzie mam wysłać monety? Daj spokój."
|
||||
hot.sting,"Nie ruszaj się. Ochrona. Skup kradzionych środków: gotówka zostaje skonfiskowana, a to trafi do twoich akt."
|
||||
hw.err.poinbase,Poinbase nie przyjmuje {0}.
|
||||
@@ -0,0 +1,980 @@
|
||||
# Probably Decentralized localization table: Russian (ru)
|
||||
# AI translation, not proofread. Source: en.csv. Format: key,text (text may be quoted; \n is a line break).
|
||||
upgrade.tab,Web3
|
||||
upgrade.title,Сообщество управления Web3
|
||||
upgrade.desc,"Участники получают торговый терминал, аппаратный кошелёк, майнинг-ферму, видеокарту RTX 60 и руководство по оценке видеокарт. В терминале доступны банк, биржа Poinbase, а также страницы Web3, «Майнинг» и «Кошельки». Другие карты и фермы продаёт Доктор Джексон."
|
||||
item.terminal.name,Торговый терминал
|
||||
item.terminal.desc,"Кошелёк, биржа Poinbase и ночной отчёт о майнинге."
|
||||
item.rig.name,Майнинг-ферма
|
||||
item.rig.desc,Вмещает до {0} видеокарт. Хешрейт {1} MH/s. Расход {2} кДж/день.
|
||||
rig.label.modules,Модули
|
||||
item.rig.modules,"Модули: хешрейт {0}, потребление {1}, износ {2}."
|
||||
item.rig.next,Слот {0}: перетащите {1} на майнинг-ферму ({2}/{3}).
|
||||
mat.common_electronic,Обычная электроника
|
||||
mat.rare_electronic,Редкая электроника
|
||||
rig.label.cards,Видеокарты
|
||||
item.gpu.name,{0} {1}
|
||||
item.gpu.desc,Номинальный хешрейт {0} MH/s. Номинальный расход {1} кДж/день. Состояние: {2}.
|
||||
item.gpu.burnt.name,Сгоревший {0} {1}
|
||||
item.gpu.burnt.desc,Эта видеокарта больше не работает.
|
||||
term.title,Торговый терминал
|
||||
tab.report,Отчёт
|
||||
wallet.line,{0}: {1} (около {2} кредитов)
|
||||
wallet.empty,Кошелёк пуст.
|
||||
wallet.total,Общая стоимость: {0} кредитов
|
||||
wallet.taint,«Грязные» средства: {0} кредитов
|
||||
trade.amount,Сумма
|
||||
trade.deposit,Депозит кредитов в CRC
|
||||
trade.withdraw,Вывод CRC в кредиты
|
||||
trade.pair,{0}/{1} ({2})
|
||||
trade.price,Цена {0}
|
||||
trade.buy,Купить
|
||||
trade.sell,Продать
|
||||
venue.Exchange,Poinbase
|
||||
venue.Dex,DEX
|
||||
venue.Darknet,Даркнет
|
||||
msg.amount,Введите сумму.
|
||||
msg.balance,Недостаточно средств.
|
||||
msg.trade,"Оплачено {0} {1}, получено {2} {3}."
|
||||
msg.deposit,Внесено {0} кредитов в CRC.
|
||||
msg.cashout,Получено {0} кредитов. Налог {1} кредитов.
|
||||
msg.aml_light,Проверка соответствия: удержаны «грязные» средства на сумму {0} кредитов.
|
||||
msg.aml_heavy,"Проверка соответствия: изъяты «грязные» средства на сумму {0} кредитов, направлен отчёт в Службу безопасности."
|
||||
report.none,Отчётов о майнинге пока нет.
|
||||
report.day,Ночь дня {0}
|
||||
report.rigs,Фермы с питанием: {0} из {1}
|
||||
report.hash,Хешрейт: {0} MH/s (сеть {1} MH/s)
|
||||
report.mined,Добыто: {0} PSC (около {1} кредитов)
|
||||
report.energy,Расход энергии: {0} кДж
|
||||
report.burnt,Сгорело видеокарт: {0}
|
||||
report.price,Цена PSC: {0} кредитов
|
||||
nightlog.mined,Майнинг-фермы добыли {0} PSC.
|
||||
nightlog.burnt,Сгорела видеокарта {0}.
|
||||
coinpay.line,Сделка: {0} {1}.
|
||||
nightlog.coinpay,Оплата монетами составила {0} кредитов; средства поступили в горячий кошелёк.
|
||||
nightlog.unpowered,Майнинг-ферм или асик-майнеров без питания: {0}.
|
||||
news.open.title,Листинг PSC на Poinbase
|
||||
news.open.desc,Биржа Верхнего уровня Poinbase открыла торги PSC в паре с CRC. Спрос на видеокарты растёт по всей станции.
|
||||
news.halving.title,Награда за блок PSC снижена вдвое
|
||||
news.halving.desc,Теперь майнеры получают вдвое меньше монет за ночь.
|
||||
appraisal.gpu,Видеокарта
|
||||
dealer.name,Дилер подержанного оборудования
|
||||
dealer.line1.1,Карты после закрытия фермы. Состояние указано рядом с названием.
|
||||
dealer.line1.2,"Несколько карт после майнинга, отдаю дёшево."
|
||||
dealer.line1.3,Подобрал по дороге. Цена из первых рук.
|
||||
dealer.line2.1,"Смотри сам, переверни и проверь с обратной стороны."
|
||||
dealer.line2.2,"Без гарантии. Смотри внимательно, прежде чем брать."
|
||||
dealer.line2.3,"Если берёшь, о цене договоримся."
|
||||
inspect.flip.back,Перевернуть
|
||||
inspect.flip.front,Лицевая сторона
|
||||
item.gpu.grade.1,как новое
|
||||
item.gpu.grade.2,приличное
|
||||
item.gpu.grade.3,заметно изношенное
|
||||
item.gpu.grade.4,сильно изношенное
|
||||
point.none.1,Тут всё в порядке. Ты ошибся.
|
||||
point.none.2,"Где? Не придумывай, если не покупаешь."
|
||||
point.worn.1,"...Ладно, есть такое. Скину немного."
|
||||
point.worn.2,"Глаз у тебя зоркий. Ладно, вот эта цена."
|
||||
point.fake.1,...Поймал-таки. Она перепрошита. Отдам по реальной цене.
|
||||
point.fake.2,"Тьфу, чип не родной. Ладно, отдам по цене настоящего чипа."
|
||||
lbl.fan.0,Лопасти чистые
|
||||
lbl.fan.1,Лопасти в пыли
|
||||
lbl.fan.2,Скол на лопасти
|
||||
lbl.fingers.0,Блестящие
|
||||
lbl.fingers.1,Потускневшие
|
||||
lbl.fingers.2,Окисленные
|
||||
lbl.print.0,Соответствует модели
|
||||
lbl.print.1,Указана другая модель
|
||||
lbl.print.2,"Перепечатано, криво"
|
||||
lbl.said," (продавец сказал: {0})"
|
||||
lbl.point,Указать
|
||||
lbl.edit,Изменить
|
||||
cust.fake.1,На этикетке написано другое. Пытаешься всучить мне подделку?
|
||||
cust.fake.2,"Модель не совпадает. Чип совсем не тот, что заявлен."
|
||||
cust.worn.1,В описании было другое. Ты умолчал о дефектах.
|
||||
cust.worn.2,Состояние на этикетке указано неверно. По такой цене не возьму.
|
||||
lbl.row.fan,Лопасти
|
||||
lbl.row.fingers,Контакты
|
||||
lbl.row.bracket,Планка
|
||||
lbl.row.print,Маркировка сзади
|
||||
lbl.row.serial,Серийный номер
|
||||
lbl.row.seal,Пломба
|
||||
lbl.bracket.0,Целая
|
||||
lbl.bracket.1,С царапинами
|
||||
lbl.serial.0,Корректный
|
||||
lbl.serial.1,Неверный код завода или длина
|
||||
lbl.serial.2,Код модели не соответствует
|
||||
lbl.seal.0,Целая
|
||||
lbl.seal.2,Отсутствует
|
||||
item.guide.name,Руководство по оценке видеокарт
|
||||
item.guide.desc,Руководство по распознаванию поддельных видеокарт и определению их стоимости.
|
||||
lbl.row.spec,Модель
|
||||
news.prehalving.title,Приближается халвинг PSC
|
||||
news.prehalving.desc,Через три дня майнеры будут получать вдвое меньше монет за ночь. Держатели ожидают роста цены.
|
||||
tab.home,Главная
|
||||
tab.bank,Банк
|
||||
tab.poinbase,Poinbase
|
||||
tab.web3,Web3
|
||||
home.enter,Войти
|
||||
home.open,Открыть
|
||||
home.summary,Кредиты {0} | Ончейн-активы около {1} кредитов
|
||||
home.lastnight,"Ночь дня {0}: добыто {1} PSC, ферм с питанием: {2} / {3}"
|
||||
entry.bank,Банк
|
||||
entry.bank.l1,"Депозиты, вывод средств, аренда"
|
||||
entry.bank.l2,Кредиты {0}
|
||||
entry.poinbase,Poinbase
|
||||
entry.poinbase.l1,Регулируемая биржа
|
||||
entry.poinbase.l2,PSC {0} кредитов
|
||||
entry.web3,Web3
|
||||
entry.web3.l2,Около {0} кредитов
|
||||
entry.help,Справка
|
||||
entry.help.l1,Руководство по Web3
|
||||
bank.cash,Кредиты: {0}
|
||||
bank.rent,"Аренда: {0} кредитов, оплата через {1} дн."
|
||||
bank.crc,Счёт Poinbase (CRC): {0}
|
||||
poin.account,"Счёт Poinbase: CRC {0}, PSC {1}"
|
||||
avg.line,Средняя цена покупки {0}: {1} кредитов
|
||||
avg.short,ср. покупка {0}
|
||||
avg.none,—
|
||||
col.asset,Актив
|
||||
col.amount,Количество
|
||||
col.value,Оценка
|
||||
col.avg,Ср. покупка
|
||||
bank.cash.k,Кредиты
|
||||
bank.rent.k,Аренда
|
||||
bank.rent.v,"{0}, оплата через {1} дн."
|
||||
bank.crc.k,Счёт Poinbase (CRC)
|
||||
poin.account.h,Счёт Poinbase
|
||||
trade.h,Торговля
|
||||
web3.wallet.h,Ончейн-кошелёк
|
||||
stable.ok,Привязан
|
||||
stable.depeg,Отвязан
|
||||
stable.warn,Внимание: покрытие резерва стейкинга на исходе
|
||||
stable.spiral,Крах
|
||||
aml.taint,Доля загрязнения счёта: {0}%
|
||||
mixer.h,Миксер
|
||||
mixer.ok,Статус: работает нормально
|
||||
mixer.sanctioned,Статус: под санкциями (дней до снятия: {0}). Выведенные в этот период монеты помечаются.
|
||||
mixer.pending,Депозиты в обработке
|
||||
mixer.none,Нет депозитов в обработке.
|
||||
mixer.col.taint,Загрязнение
|
||||
mixer.col.ready,Готовность
|
||||
mixer.day,День {0}
|
||||
mixer.deposit,Депозит
|
||||
mixer.balance,Баланс: {1} {0}
|
||||
mixer.rounds,Раунды
|
||||
mixer.preview,"Ожидается возврат {0} {1}, загрязнение снизится примерно на {2}%, готовность — день {3}."
|
||||
mixer.go,Депозит в миксер
|
||||
mixer.min,Депозит должен составлять не менее {0} кредитов.
|
||||
mixer.done,Внесено {0} {1}; возврат в день {2}.
|
||||
mixer.upgrade.title,Миксер
|
||||
mixer.upgrade.desc,"Разблокирует миксер на странице «Серая сеть» в терминале: вносите «грязные» монеты и забирайте их через несколько дней с меньшим загрязнением. Вывод недавно смешанных монет проверяется строже; во время зачисток миксер может попасть под санкции, а выведенные в этот период монеты помечаются."
|
||||
news.sanction.title,Миксер внесён в санкционный список
|
||||
news.sanction.desc,"Служба безопасности ввела санкции против ряда миксер-сервисов. Средства, выведенные из миксеров в ближайшие дни, будут считаться подозрительными."
|
||||
nightlog.mixer,Миксер вернул {0} {1}; загрязнение: {2} -> {3}.
|
||||
nightlog.mixer_flag," (выведено во время санкций; адрес помечен)"
|
||||
nightlog.mixer_rug,Оператор миксера сбежал с деньгами: {0} {1} не вернулись.
|
||||
web3.sub.trade,Торговля
|
||||
gray.sub.mixer,Миксер
|
||||
msg.frozen,Эти монеты заморожены до разморозки.
|
||||
wallet.frozen,"{0}: {1} заморожено, разморозка в день {2}"
|
||||
nightlog.crt_freeze,Чёрный рынок передал адреса во время зачистки: {0} ваших CRT заморожено до дня {1}.
|
||||
nightlog.thaw,Замороженные {0} {1} разморожены.
|
||||
news.crtfreeze.title,Чёрный рынок замораживает часть адресов CRT из-за зачистки
|
||||
news.crtfreeze.desc,"Ходят слухи, что чёрный рынок передал Службе безопасности список адресов CRT в обмен на неприкосновенность. У держателей с низкой репутацией риск заморозки выше."
|
||||
black.upgrade.title,Магазин Web3
|
||||
black.upgrade.desc,"Разблокирует магазин на странице «Серая сеть» в терминале: ончейн-филиал фракции «Чёрный рынок». Каждую неделю на полках — контрабанда, изредка — высокотехнологичные товары и видеокарты (с наценкой); покупайте на месте или оформляйте заказ с курьером. Оплата только монетами (PSC, CRT, CRA, Ponero), принимаются и «грязные» средства. Требуется репутация на чёрном рынке; во время зачисток магазин недоступен."
|
||||
black.offline,Во время зачистки ончейн-вход в магазин отключён.
|
||||
black.closed,Для входа в магазин требуется репутация на чёрном рынке: {0} (сейчас: {1}).
|
||||
black.sub.buy,Покупка
|
||||
black.shop.h,Спотовый прилавок
|
||||
black.rep,Репутация на чёрном рынке: {0}
|
||||
black.empty,На этой неделе всё распродано.
|
||||
black.offer,{0} x{1} {2} кредитов
|
||||
black.buy,Купить
|
||||
black.bought,Сделка заключена: {0} на складе.
|
||||
black.pay.h,Оплата
|
||||
black.desk.h,Пункт обмена Ponero
|
||||
black.desk.left,Остаток на сегодня: {0} (лимит {1})
|
||||
black.desk.price,Цена Ponero: {0}
|
||||
black.desk.swap,Обменять
|
||||
black.desk.in,В Ponero
|
||||
black.desk.out,Из Ponero
|
||||
black.desk.go,Обменять
|
||||
black.desk.fail,"Ошибка обмена: неверный баланс, превышен лимит или некорректная сумма."
|
||||
black.sub.orders,Заказы
|
||||
black.rugged,Платформа рухнула; до возобновления торговли дней: {0}.
|
||||
black.seller,"Сделок: {1}, положительных: {2}%"
|
||||
black.orders.h,Каталог заказов
|
||||
black.order,Заказать
|
||||
black.mode.Escrow,Эскроу
|
||||
black.mode.Advance,Досрочная выплата
|
||||
black.ordered,"Заказано: {0}, доставка в день {1}."
|
||||
black.mine.h,Мои заказы
|
||||
black.mine.none,Заказов пока нет.
|
||||
black.mine.line,"{0} ({1}, {2}): {3}, день {4}"
|
||||
black.state.Pending,в пути
|
||||
black.state.Ready,доставлено
|
||||
black.state.Done,получено
|
||||
black.state.Refunded.scam,"продавец сбежал, оформлен возврат"
|
||||
black.state.Lost.scam,"продавец сбежал, деньги потеряны"
|
||||
black.state.Lost.rug,"рагпул платформы, деньги потеряны"
|
||||
black.state.Lost.intercept,перехвачено
|
||||
black.forum.h,Информация с форума
|
||||
black.forum.quiet,В последнее время всё тихо.
|
||||
black.forum.scam,"Говорят, {0} забирает деньги и ничего не отправляет."
|
||||
black.forum.rug,"Вывод средств в последнее время замедлился, на сайте идут акции, а жалобы на форуме активно удаляют."
|
||||
nightlog.bm.scam_refund,Чёрный рынок: продавец {0} сбежал; средства из эскроу за {1} возвращены.
|
||||
nightlog.bm.scam_loss,Чёрный рынок: продавец {0} получил досрочную выплату и сбежал; {1} потерян ({2} кредитов).
|
||||
nightlog.bm.intercept,Чёрный рынок: посылка с {0} перехвачена; потеряна оплата в размере {1} кредитов.
|
||||
nightlog.bm.rug,Чёрный рынок: платформа совершила рагпул; средства в пути за {0} ({1}) потеряны.
|
||||
nightlog.bm.reopen,Чёрный рынок: на прежнем месте снова кто-то открылся.
|
||||
news.bmrug.title,Рагпул платформы на чёрном рынке
|
||||
news.bmrug.desc,"Ончейн-вход чёрного рынка закрылся за одну ночь, обнулив все средства в эскроу и досрочных выплатах. Новый вход появится через несколько дней."
|
||||
courier.name,Курьер
|
||||
courier.line1.1,Доставка прибыла.
|
||||
courier.line1.2,Тебе посылка.
|
||||
courier.line2.1,"Не говори мне, что внутри. Я и знать не хочу."
|
||||
courier.line2.2,Оставил здесь. Я пошёл.
|
||||
gray.sub.black,Магазин
|
||||
black.stock,Осталось: {0}
|
||||
black.price,{0} кред.
|
||||
black.noadvance,Без досрочной выплаты
|
||||
black.kind.gpu,Видеокарта состояние {0}%
|
||||
black.kind.Contraband.1,Контрабанда (низк.)
|
||||
black.kind.Contraband.2,Контрабанда (средн.)
|
||||
black.kind.Contraband.3,Контрабанда (высок.)
|
||||
black.kind.Tech,Высокие технологии (наценка)
|
||||
nightlog.bm.ready,Чёрный рынок: доставлен товар «{0}»; курьер заглянет после открытия.
|
||||
guide.web3.title,Руководство по Web3
|
||||
guide.web3.text,"Банк и торговля: страница банка только для чтения и показывает наличные, аренду и CRC на счёте Poinbase. Страница «Средства» в Poinbase отвечает за ввод и вывод; сначала выбирается монета: CRC можно вводить и выводить через банковский счёт или кошелёк, остальные монеты только через кошелёк. Депозит из банка конвертирует кредиты в CRC на счёте Poinbase; вывод в банк меняет CRC обратно на кредиты и проходит проверку соответствия, оценивающую загрязнение счёта Poinbase. Вывод на кошелёк требует адрес получателя и нескольких подтверждений до зачисления; комиссия за газ фиксирована на обычном уровне и списывается с отправляемой монеты. Неверный формат адреса или контрольная сумма приводят к отказу; адрес с верным форматом, которым никто не пользуется, означает потерю отправленных монет.¶Торговля: PSC означает Probably Stolen Coin — это монета, которую добывают видеокарты и асик-майнеры. На спотовом рынке Poinbase две пары, PSC/CRC и SPARK/CRC, по монете, выбранной на графике. И покупка, и продажа вводятся как количество торгуемой монеты; в предпросмотре видно, сколько котируемой монеты уйдёт или придёт, средняя цена включает комиссию, проскальзывание — нет.¶На торговой странице Web3 можно обменять любые две монеты, всегда через CRC: если CRC с одной стороны, используется один пул, иначе два пула, две комиссии и суммирующееся проскальзывание; предпросмотр показывает получаемое количество, число пулов и потери. Обмен стейблкоинов (CRT или CRA на CRC) идёт через стабильные пулы: комиссия {StableFee:%} и почти нулевое проскальзывание возле привязки; при отвязке ликвидность редеет, при обвале её выводят, и проскальзывание резко растёт.§Аппаратные кошельки: ончейн-монеты хранятся на аппаратных кошельках PLEDGER, баланс и загрязнение у каждого свои. Кошелёк — это предмет: перетащите его на торговый терминал, чтобы загрузить. Открывайте его на странице «Кошельки» терминала; подключайте и отключайте в правом верхнем углу терминала. Торговля на странице Web3, магазин и миксер на странице «Серая сеть» используют подключённый кошелёк; без кошелька или без подключения они доступны только для просмотра, а все балансы равны 0. Покупатели, платящие монетами, платят на подключённый кошелёк.¶Платежи (магазин, миксер, пункт обмена Ponero, комиссия за размещение) начинаются со счёта на терминале; введите адрес получателя на кошельке и удерживайте ✓, чтобы подписать. Последние два символа адреса — контрольная сумма, поэтому опечатка в один символ обычно отсекается; изредка адрес случайно оказывается валидным, и монеты уходят на адрес, которым никто не пользуется. Для обмена на DEX также требуется подпись на кошельке.¶Poinbase — кастодиальный аккаунт; депозит отправляется с кошелька на адрес депозита Poinbase (только PSC, CRC и SPARK; регулируемая биржа не принимает ни CRT чёрного рынLine truncated
|
||||
courier.odd1,...Посылка пришла.
|
||||
courier.odd2,(Его рука остаётся в кармане.) Подпиши здесь.
|
||||
courier.sign,Подписать
|
||||
courier.refuse,Отказаться
|
||||
courier.signed,"Хорошо. Не двигаться, Служба безопасности."
|
||||
courier.refused,"...Ладно, забудь."
|
||||
black.state.Lost.seized,изъято
|
||||
black.state.Lost.refused,отказ
|
||||
black.forum.easy,"В последнее время всё слишком гладко: продавцы отправляют быстрее обычного, да ещё и появились новые аккаунты, которых никто не знает."
|
||||
black.forum.busted,"Говорят, {0} арестован, а записи заказов всё ещё остались."
|
||||
nightlog.bm.trap.honeypot,"Чёрный рынок: платформа была перехвачена силовиками; ваш {0} отслежен, зафиксирована улика: {1}."
|
||||
nightlog.bm.trap.seller,"Чёрный рынок: продавец арестован, и сохранённые записи заказов скомпрометировали вас: {0}, зафиксирована улика: {1}."
|
||||
tab.mining,Майнинг
|
||||
courier.sign.say,Я подпишу.
|
||||
courier.refuse.say,Не приму. Отправляйте обратно.
|
||||
black.forum.busted_buyer,"Говорят, недавно задержали группу покупателей, а записи о сделках остались на платформе."
|
||||
nightlog.bm.sale_sold,Чёрный рынок: ваш {0} продан за {1}; выплата в день {2}.
|
||||
nightlog.bm.sale_paid,"Чёрный рынок: выплата {1} за {0} получена (CRT), «грязные» средства: {2}."
|
||||
nightlog.bm.sale_fake,Чёрный рынок: покупатель распознал подделку ({0}) и вернул товар; ваш рейтинг снизился.
|
||||
nightlog.bm.sale_rug,Чёрный рынок: платформа совершила рагпул; ваш {0} и выплата ({1}) пропали.
|
||||
black.sub.sell,Продажа
|
||||
black.sell.h,Продажа
|
||||
black.sell.mult,Множитель цены
|
||||
black.sell.none,На складе нет подходящих для продажи предметов.
|
||||
black.sell.rating,Рейтинг: {0}%
|
||||
black.mine.sale,{0} справ. {1} цена {2} (x{3}): {4}
|
||||
black.sale.Listed,в продаже
|
||||
black.sale.Paid,выплачено
|
||||
black.sale.Lost,"рагпул платформы, пропало"
|
||||
black.sale.Delisted,снято
|
||||
black.sale.Delisted.fake,покупатель выявил подделку и вернул товар
|
||||
black.kind.gpunew,Видеокарта новая
|
||||
merchant.GpuNew,Новые видеокарты
|
||||
merchant.GpuUsed,Б/у видеокарты
|
||||
merchant.Arms,Оружие
|
||||
merchant.Docs,Ключ-карты и чипы
|
||||
merchant.Pharma,Фарма
|
||||
merchant.Bulk,Опт
|
||||
black.days,Доставка: {0} дн.
|
||||
black.sell.listedall,Выставлено: {0} шт.
|
||||
merchant.Rigs,Фермы и питание
|
||||
merchant.Modules,Модули
|
||||
merchant.GunMods,Оружейные детали
|
||||
merchant.Chem,Химикаты
|
||||
merchant.Brewer,Пивоварение
|
||||
merchant.Farm,Гидропоника
|
||||
merchant.Husbandry,Животноводство
|
||||
merchant.Miner,Шахтёрские товары
|
||||
merchant.Water,Водоснабжение
|
||||
merchant.Storage,Хранение
|
||||
merchant.Tools,Инструменты
|
||||
merchant.Luxury,Роскошь
|
||||
black.kind.Goods,Товары
|
||||
merchant.Elite,Элитный магазин
|
||||
merchant.Personal,Частный продавец
|
||||
black.pay.confirm,Счёт
|
||||
black.pay.to,Адрес получателя: {0}
|
||||
black.pay.cancel,Аннулировать
|
||||
pay.mix,Миксер {0} {1}
|
||||
pay.swap,Пункт обмена Ponero {0} {1}
|
||||
black.edit.cancel,Отмена
|
||||
merchant.Platform,Платформа
|
||||
black.platform.line,Спот платформы мгновенная доставка
|
||||
black.orders.in,Покупки
|
||||
black.orders.out,Продажи
|
||||
black.desk.pair,PONERO [приватная монета] цена {0}
|
||||
black.pay.amount,Сумма: {0} {1} (около {2} кредитов)
|
||||
black.pay.wallet,Оплатить из кошелька
|
||||
hw.total,Итого ≈ {0} кредитов
|
||||
hw.pending.bill,К оплате: {0}
|
||||
hw.pending.sign,На подпись: {0}
|
||||
hw.send,Отправить
|
||||
hw.review,Запрос подписи
|
||||
hw.to,Адрес получателя
|
||||
hw.avail,Доступно {1} {0}
|
||||
hw.amount,Сумма
|
||||
hw.bill,Счёт: {0} {1} {2}
|
||||
hw.fill,Заполнить из счёта
|
||||
hw.next,✓ Далее × Назад
|
||||
hw.err.format,Неверный формат адреса.
|
||||
hw.err.checksum,Ошибка контрольной суммы адреса.
|
||||
hw.err.self,Это адрес текущего кошелька.
|
||||
hw.err.asset,В счёте требуется {0}.
|
||||
hw.err.short,Меньше суммы счёта: {0} {1}.
|
||||
hw.err.nobill,Нет неоплаченных счетов от этого получателя.
|
||||
hw.review.h,Проверка
|
||||
hw.contract,Вызов контракта
|
||||
hw.review.to,Адрес получателя
|
||||
hw.review.amount,{0} {1} (около {2} кредитов)
|
||||
hw.review.bill,Счёт: {0}
|
||||
hw.review.unknown,У этого адреса нет истории транзакций.
|
||||
hw.review.over,Переплата {0} {1}; излишек не возвращается.
|
||||
hw.hold,Удерживайте ✓ для подписи × Отклонить
|
||||
hw.tx.h,Транзакция
|
||||
hw.tx.signing,Подписание…
|
||||
hw.tx.mempool,Отправлено в сеть; ожидание в мемпуле…
|
||||
hw.tx.packed,Включено в блок #{0}
|
||||
hw.tx.confirm,Блок #{0} подтверждение {1}/{2}
|
||||
hw.skip,Пропустить
|
||||
hw.done.h,Подтверждено
|
||||
hw.done.block,Блок #{0}
|
||||
hw.done.sent,{0} {1} → {2}
|
||||
hw.done.void,Этот адрес никем не используется. Средства потеряны.
|
||||
hw.back,Назад
|
||||
hw.rejected,Подписание отклонено на кошельке.
|
||||
hw.wait,Подтвердите на кошельке.
|
||||
hw.swap,Обмен {0} {1} → около {2} {3}
|
||||
tab.wallets,Кошельки
|
||||
hw.wallet.n,Кошелёк {0}
|
||||
hw.review.own,Свой кошелёк: {0}
|
||||
hw.review.poinbase,Адрес депозита Poinbase
|
||||
poin.deposit,Адрес депозита: {0}
|
||||
wallets.count,Кошельки {0}/{1}
|
||||
wallets.col.name,Название
|
||||
wallets.col.addr,Адрес
|
||||
wallets.col.taint,Грязные
|
||||
wallets.open,Открыть
|
||||
wallets.use,Подключить
|
||||
wallets.current,Подключено
|
||||
wallets.added,Добавлено {0}: {1}
|
||||
nightlog.drained,"Из {0} выведены монеты, около {1} кредитов."
|
||||
item.hwwallet.name,Аппаратный кошелёк PLEDGER
|
||||
item.hwwallet.desc,"Аппаратный кошелёк с большим экраном. Перетащите на торговый терминал, чтобы добавить кошелёк (до 5)."
|
||||
poin.empty,Счёт пуст.
|
||||
hw.copy,Копировать
|
||||
hw.paste,Вставить
|
||||
hw.copied,Адрес скопирован.
|
||||
hw.copied.addr,Скопировано: {0}
|
||||
hw.balance.frozen," (заморожено {0})"
|
||||
wallets.destroy,Уничтожить
|
||||
wallets.destroy.sure,Подтвердить
|
||||
wallets.destroyed,Уничтожен {0}: {1}
|
||||
wallets.destroy.warn,Уничтожение {0} навсегда лишает его монет. Нажмите ещё раз для подтверждения.
|
||||
payout.label,Выплата
|
||||
payout.unset,Не задан
|
||||
payout.set,Задать адрес
|
||||
payout.h,Адрес выплаты
|
||||
payout.cur,Текущий: {0}
|
||||
payout.pick,Свои кошельки:
|
||||
payout.manual,Или введите адрес:
|
||||
payout.clear,Очистить
|
||||
payout.err,Неверный адрес.
|
||||
nightlog.mined.lost,"Добыто {0} PSC, но они потеряны: адрес выплаты не задан или его кошелёк уничтожен."
|
||||
wallets.none,Кошелёк не загружен. Перетащите аппаратный кошелёк на терминал.
|
||||
web3.err.noconn,Кошелёк не подключён.
|
||||
web3.connect,Подключить кошелёк
|
||||
web3.disconnect,Отключить
|
||||
web3.conn,{0} {1}
|
||||
hw.balance.value,≈ {0}
|
||||
wallets.rename,Переименовать
|
||||
wallets.rename.h,Новое имя для {0}
|
||||
wallets.rename.ok,ОК
|
||||
hw.fee.slow,Медленно
|
||||
hw.fee.normal,Обычно
|
||||
hw.fee.fast,Быстро
|
||||
hw.fee,Комиссия за газ {0} {1} (около {2} кредитов)
|
||||
hw.confs,Требуется подтверждений: {0}
|
||||
hw.congested,Сеть перегружена
|
||||
hw.congested.slow,Сеть перегружена: транзакция с низкой комиссией может быть исключена из мемпула
|
||||
hw.recent,Недавние
|
||||
hw.recent.out,→ {0} {1} {2}
|
||||
hw.recent.in,← {0} {1} {2}
|
||||
hw.review.history,Адрес есть в истории
|
||||
hw.tx.stuck,В очереди мемпула…
|
||||
hw.tx.dropped,Исключена из мемпула. Ничего не отправлено; комиссия за газ списана.
|
||||
hw.dropped.h,Не отправлено
|
||||
hw.err.fee,Недостаточно средств для оплаты комиссии за газ.
|
||||
news.congest.title,Перегрузка сети
|
||||
news.congest.desc,"Ажиотаж вокруг аирдропа перегрузил сеть. Комиссии за газ выросли в несколько раз, а транзакции с низкой комиссией могут быть исключены из мемпула."
|
||||
news.phish.title,Уведомление Poinbase: миграция адреса депозита
|
||||
news.phish.desc,Poinbase обновила систему кошельков. Старый адрес для депозита будет отключён; отправляйте активы на новый адрес {0}.
|
||||
black.forum.phish,"Кто-то выложил новый адрес миксера: {0}, заявив, что за старым следят."
|
||||
hw.gas,Газ ×{0}
|
||||
web3.sub.stake,Стейкинг
|
||||
stake.h,Пул стейкинга Революционеров
|
||||
stake.rate,"Дневная ставка {0}%; вывод без процентов, ожидание (дней): {1}"
|
||||
stake.low,Покрытие резерва на исходе; ставка снижена
|
||||
stake.cra,Цена CRA {0} {1}
|
||||
stake.none,В стейкинге ничего нет.
|
||||
stake.col.wallet,Кошелёк
|
||||
stake.col.amount,В стейкинге
|
||||
stake.col.queue,Разблокировка
|
||||
stake.day," (день {0})"
|
||||
spark.price,Балансовый токен SPARK {0} кредитов
|
||||
stake.ops,{0}
|
||||
stake.avail,CRA {0} В стейкинге {1}
|
||||
stake.do,В стейкинг
|
||||
stake.undo,Запросить вывод
|
||||
stake.sum.in,Внести {0} CRA в стейкинг
|
||||
stake.sum.out,Запросить вывод {0} CRA (дней до зачисления: {1})
|
||||
stake.done.in,{0} CRA внесено в стейкинг.
|
||||
stake.done.out,Запрошен вывод {0} CRA; возврат в кошелёк на день {1}.
|
||||
nightlog.stakeint,Доход от стейкинга: +{0} CRA.
|
||||
nightlog.unstaked,Выведенные из стейкинга {0} CRA вернулись в {1}.
|
||||
news.crawarn.title,Волнения вокруг пула стейкинга Революционеров
|
||||
news.cralow.title,Революционеры снижают ставку стейкинга
|
||||
stake.avail2,SPARK {0}
|
||||
poin.sub.spot,Спот
|
||||
poin.sub.perp,Бессрочные
|
||||
perp.h,Бессрочные фьючерсы
|
||||
perp.acct,Маржинальный счёт CRC {0}
|
||||
perp.debt,Долг: {0}; до конфискации имущества дней: {1}. До погашения открытие позиций и вывод средств недоступны.
|
||||
perp.banned,Счёт бессрочных фьючерсов заблокирован; дней до снятия блокировки: {0}.
|
||||
perp.none,Нет позиций.
|
||||
perp.col.pos,Позиция
|
||||
perp.col.notional,Номинальная стоимость
|
||||
perp.col.price,Вход → цена
|
||||
perp.col.pnl,PnL
|
||||
perp.col.liq,Цена ликв.
|
||||
perp.long,Лонг
|
||||
perp.short,Шорт
|
||||
perp.rate,{0} цена {1} ставка финансирования {2}%/ночь
|
||||
perp.fund,Страховой фонд {0}
|
||||
perp.open,Открыть
|
||||
perp.margin,Сумма маржи (CRC)
|
||||
perp.do.open,Открыть
|
||||
perp.do.add,+ Маржа
|
||||
perp.do.close,Закрыть
|
||||
perp.opened,"Открыто {0} {1}: маржа {2} CRC, {3}×."
|
||||
perp.added,Добавлено {0} CRC маржи.
|
||||
perp.closed,Позиция закрыта; {0} CRC возвращено на счёт (PnL {1}).
|
||||
perp.deficit,"Недостаток средств на счёте: {0}, покрыт страховым фондом и долгом."
|
||||
perp.err.Banned,Счёт бессрочных фьючерсов заблокирован.
|
||||
perp.err.Debt,У вас есть задолженность; открытие новых позиций запрещено.
|
||||
perp.err.Leverage,Плечо превышает лимит для этого инструмента.
|
||||
perp.err.Size,Превышен лимит размера позиции для этого инструмента.
|
||||
perp.err.Funds,Недостаточно CRC на счёте (с учётом комиссии).
|
||||
perp.err.Opposite,Нельзя одновременно открывать лонг и шорт по одному инструменту; сначала закройте текущую позицию.
|
||||
perp.err.NoPosition,Нет позиции.
|
||||
perp.err.Margin,Введите сумму маржи.
|
||||
perp.debt.block,У вас задолженность по фьючерсам; вывод заблокирован.
|
||||
nightlog.perp.liq,{0} ликвидирована; маржа {1} списана.
|
||||
nightlog.perp.adl,"Страховой фонд исчерпан; по {0} сработал автоделевериджинг, удержано {1} прибыли."
|
||||
nightlog.perp.interest,Начислены проценты на долг по бессрочным фьючерсам; текущий долг: {0}.
|
||||
nightlog.perp.seize,Просрочен долг по бессрочным фьючерсам: изъятое имущество покрыло {0}.
|
||||
nightlog.perp.writeoff," Списано {0}; счёт бессрочных фьючерсов заблокирован, дней блокировки: {1}."
|
||||
perp.slip.title,Акт изъятия за долг по бессрочным фьючерсам
|
||||
perp.preview2,Комиссия {0} ликв. {1}
|
||||
nightlog.perp.repaid,Дефицит по бессрочным фьючерсам: со счёта Poinbase списано {0} CRC в счёт погашения.
|
||||
perp.err.Thin,Проскальзывание по этому ордеру слишком велико: позиция сразу ликвидируется. Уменьшите сумму или плечо.
|
||||
perp.err.Single,Одна позиция за раз; пополните маржу.
|
||||
mat.hypertech_electronic,Гипертехнологичный электронный компонент
|
||||
item.asic.name,Асик-майнер RatDigg {0}
|
||||
item.asic.dead.name,Сгоревший асик-майнер RatDigg {0}
|
||||
item.asic.desc,"Номинальный хешрейт {0} GH/s. Номинальный расход {1} кДж/день. Состояние: {2}. Автономный асик-майнер: работает от батареи, поддерживает модули."
|
||||
item.asic.dead.desc,Сгорел. Перетащите на него электронные компоненты для починки: сейчас требуется {0} × {1}. После починки прочность снизится на 20.
|
||||
item.asic.dead.fixed,Уже починено.
|
||||
merchant.Asic,Дилер асик-майнеров
|
||||
black.kind.asic,Асик-майнер состояние {0}%
|
||||
black.kind.asicnew,Асик-майнер новый
|
||||
news.erawarn.title,RatDigg скоро выпустит новое поколение асик-майнеров
|
||||
news.erawarn.desc,"Производитель асик-майнеров анонсировал новинки. В отрасли ожидают, что крупные фермы вскоре массово обновят парк. Поговаривают, дни майнинга на видеокартах сочтены."
|
||||
news.era.title,Эра асик-майнеров
|
||||
news.era.desc,"Новое поколение асик-майнеров пошло в серию, а крупные фермы вдвое снизили затраты на энергию. Хешрейт сети поползёт вверх, а доходность майнинга на видеокартах будет размыта."
|
||||
web3.sub.predict,Прогнозы
|
||||
predict.h,Рынок предсказаний
|
||||
predict.acct,{0}: CRC {1}
|
||||
predict.none,Сегодня нет открытых рынков.
|
||||
predict.closed,закрыто
|
||||
predict.row,Да {0} Нет {1}
|
||||
predict.held,"в портфеле {0} x{1}, затраты {2}"
|
||||
predict.yes,Да
|
||||
predict.no,Нет
|
||||
predict.void,аннулировано
|
||||
predict.result,День {0} {1} результат: {2} {3}
|
||||
predict.pick,Сделка
|
||||
predict.price,Цена доли: Да {0} Нет {1}
|
||||
predict.pos,{0}: {1} x{2}
|
||||
predict.pos2,Затраты {0} выплата {1}
|
||||
predict.sum.buy,Покупка {1} за {2} CRC: {0}
|
||||
predict.sum.sell,Продажа позиции в прогнозе: {0}
|
||||
predict.closed.note,"Закрыто, ожидается расчёт."
|
||||
predict.preview,"Купить {0}: ~{1} долей (ср. {2}), чистыми {3} при успехе"
|
||||
predict.buy.yes,Купить «Да»
|
||||
predict.buy.no,Купить «Нет»
|
||||
predict.sell,Продать всё
|
||||
predict.bought,"Куплено {0} за {2}, выплата {1} при верном исходе."
|
||||
predict.sold,"Продано, получено {0}."
|
||||
predict.err.Closed,Этот рынок закрыт.
|
||||
predict.err.Amount,Неверная сумма.
|
||||
predict.err.Funds,В кошельке недостаточно CRC.
|
||||
predict.err.Cap,Превышен лимит позиции на этом рынке.
|
||||
predict.err.Opposite,У вас открыта противоположная позиция; сначала продайте её.
|
||||
predict.err.NoPosition,Нет открытой позиции на этом рынке.
|
||||
predict.win.one,День {0}
|
||||
predict.win.range,Дни {0}-{1}
|
||||
predict.q.event,{0}: произойдёт «{1}»
|
||||
predict.q.faction,{0}: {1} начнёт операцию
|
||||
predict.q.purity,{0}: чистота {1} >= {2}
|
||||
predict.q.price,{0}: цена {1} >= {2}
|
||||
predict.faction.FACTION_SECURITY,Служба безопасности
|
||||
predict.faction.FACTION_REVOLUTION,Революционеры
|
||||
predict.faction.FACTION_LOWER_LEVEL,Нижний уровень
|
||||
predict.faction.FACTION_UPPER_LEVEL,Верхний уровень
|
||||
predict.faction.FACTION_BLACK_MARKET,Чёрный рынок
|
||||
predict.purity.gutter,Вода нижнего уровня
|
||||
predict.purity.rust,Вода верхнего уровня
|
||||
nightlog.predict.win,"Прогноз сбылся: «{0}», выплачено {1}."
|
||||
nightlog.predict.lose,"Прогноз не оправдался: «{0}», ставка {1} потеряна."
|
||||
nightlog.predict.void,"Прогноз аннулирован: «{0}», ставка {1} возвращена."
|
||||
nightlog.predict.caught,"Вскрыта инсайдерская сделка: «{0}», ставка и выигрыш {1} конфискованы, зафиксировано мошенничество."
|
||||
predict.tab.markets,Рынки
|
||||
predict.tab.intel,Информация
|
||||
predict.acct.crt,{0}: CRT {1}
|
||||
predict.tier.0,низкий
|
||||
predict.tier.1,средний
|
||||
predict.tier.2,высокий
|
||||
predict.clue.tip,Наводка ({0}): «{1}»
|
||||
predict.clue.queued,Запланировано: старт на день {0}
|
||||
predict.clue.queued2,Запланировано: день {0} «{1}»
|
||||
predict.clue.cool,Событие активно или на перезарядке
|
||||
predict.clue.busy,Операция фракции активна; новой пока не будет
|
||||
predict.clue.halving,Халвинг в день {0}; якорь растёт за неделю до него
|
||||
predict.clue.anchor,Текущий якорь цены: {0}
|
||||
predict.clue.gas,Газ за последнее время: {0}
|
||||
predict.clue.drain,Расход за ночь: {0}
|
||||
predict.clue.era,"Случайно в дни {0}-{1}, объявляется заранее"
|
||||
predict.clue.era.warned,Объявлено: старт в дни {0}-{1}
|
||||
predict.q.gas,{0}: индекс газа >= {1}
|
||||
predict.q.cra,{0}: выдано предупреждение по CRA
|
||||
predict.q.era,{0}: начинается эра асик-майнеров
|
||||
predict.era,Эра асик-майнеров
|
||||
predict.pos3,Сред. {0} сейчас {1}
|
||||
predict.pos4,При продаже сейчас вернётся {0}
|
||||
intel.h,Торговец информацией
|
||||
intel.locked,Требуются магазин Web3 и репутация на Чёрном рынке: {0}.
|
||||
intel.brief.buy,Купить сводку обстановки ({0} CRT)
|
||||
intel.brief.none,Сводка ещё не куплена.
|
||||
intel.brief.day,Сводка за день {0}
|
||||
intel.tips.h,Инсайдерские наводки
|
||||
intel.tips.none,Не о чем спросить (только операции фракций и эра асик-майнеров).
|
||||
intel.tip.buy,Точность около {0}% {1} CRT
|
||||
intel.err.funds,"В кошельке недостаточно CRT, или рынок больше недоступен для покупки."
|
||||
intel.brief.sum,"Сводка обстановки, {0} CRT"
|
||||
intel.tip.sum,Инсайдерская наводка за {0} CRT: {1}
|
||||
intel.brief.done,Сводка получена.
|
||||
intel.tip.done,Говорят: {0}.
|
||||
predict.brief.levels,Служба безоп. {0} Револ. {1} Чёрный рынок {2} Волнения {3} Верх. ур. {4}
|
||||
predict.brief.busy,{0}: операция идёт
|
||||
predict.brief.queued,{0}: операция запланирована
|
||||
predict.brief.none,{0}: нечего запускать
|
||||
predict.brief.can,{0}: можно начать {1}
|
||||
predict.clue.push,Вы сдвинули цену на {0}%: рискованно
|
||||
nightlog.predict.manip,"Прогноз признан манипуляцией ценой: «{0}», ставка {1} конфискована, зафиксировано мошенничество."
|
||||
news.manip.title,Биржа расследует подозрительные сделки
|
||||
news.manip.desc,Регуляторы сообщают: некто манипулировал ценой крупными спотовыми ордерами и получал прибыль на деривативах и прогнозах; средства изъяты.
|
||||
perp.manip,"Прибыль {0} при закрытии признана манипуляцией ценой и изъята; счёт бессрочных фьючерсов заморожен, дней заморозки: {1}."
|
||||
web3.sub.ponzi,Доходность
|
||||
ponzi.h,Схема Понци
|
||||
ponzi.acct,Кошелёк эмитента {0}: CRC {1}
|
||||
ponzi.rate,Дневная ставка {0}%
|
||||
ponzi.pool,Пул {0} / лимит {1}
|
||||
ponzi.inflow,Новые депозиты за ночь: {0}
|
||||
ponzi.interest,Проценты к выплате сегодня ночью: {0}
|
||||
ponzi.own,"Проценты, выплаченные из своего кармана: {0}"
|
||||
ponzi.wind,Риск доноса: {0}
|
||||
ponzi.wind.low,низкий
|
||||
ponzi.wind.mid,средний
|
||||
ponzi.wind.high,высокий
|
||||
ponzi.idle,Схема не запущена.
|
||||
ponzi.done,Схема закрыта; доступна только одна за сохранение.
|
||||
ponzi.ops,Действия
|
||||
ponzi.rug,Совершить рагпул ({0})
|
||||
ponzi.rug.confirm,Нажмите ещё раз для подтверждения рагпула на {0}
|
||||
ponzi.rugged,"Забрано {0}, полностью «грязные» средства."
|
||||
ponzi.open,Запустить схему
|
||||
ponzi.ad,Расходы на рекламу: {0} CRC с текущего кошелька; требуется подпись.
|
||||
ponzi.start,Запустить
|
||||
ponzi.started,Запущено.
|
||||
ponzi.err,В кошельке недостаточно CRC для оплаты рекламы.
|
||||
nightlog.ponzi.collapse,"Схема не смогла выплатить проценты; паника вкладчиков, {0} из пула конфисковано, зафиксировано мошенничество, репутация на Нижнем уровне обнулена."
|
||||
nightlog.ponzi.reported,"На схему поступил донос; {0} из пула конфисковано, зафиксировано мошенничество, репутация на Нижнем уровне обнулена."
|
||||
news.ponzi.title,Крах схемы Понци
|
||||
news.ponzi.desc,"На схему Понци на Нижнем уровне поступил донос; инвесторы осаждают офис, а регуляторы заморозили средства."
|
||||
news.ponzi.rug.title,Инвестиционное мошенничество
|
||||
news.ponzi.rug.desc,Создатель схемы Понци сбежал со всеми средствами; инвесторы с Нижнего уровня потеряли всё.
|
||||
ponzi.start.sum,"Запустить схему Понци, дневная ставка {0}%, реклама {1} CRC"
|
||||
ponzi.rug.sum,Рагпул пула {0}
|
||||
ponzi.err.wallet,Подпишите кошельком создателя.
|
||||
predict.clue.counter,"Информация: запланировано (информатор у стойки, записка со слухами)"
|
||||
web3.sub.airdrop,Аирдропы
|
||||
air.h,Аирдропы
|
||||
air.none,Сейчас нет доступных аирдропов.
|
||||
air.row,{0} награда: {1} CRC {2} до дня {3}
|
||||
air.claim,Получить
|
||||
air.unlimited,одобрить {0} без ограничений
|
||||
air.limited,одобрить {0}: {1}
|
||||
air.approvals,Одобрения {0}
|
||||
air.approvals.none,Нет одобрений.
|
||||
air.approval,{0}: {1}
|
||||
air.revoke,Отозвать
|
||||
air.sum,Получить аирдроп {0} ({1})
|
||||
air.claimed,Получено {0} CRC.
|
||||
air.auth,Авторизовать кошелёк
|
||||
air.unauth,Не авторизовано
|
||||
air.authed,Авторизовано: {0}
|
||||
air.authed.msg,Кошелёк авторизован для {0}.
|
||||
air.auth.sum,Авторизовать {0} для действий от имени этого кошелька. Объём: {1}.
|
||||
air.err.unauth,Сначала авторизуйте кошелёк для этого аирдропа.
|
||||
air.revoke.sum,Отозвать одобрение {0} на {1}
|
||||
air.revoked,Одобрение отозвано.
|
||||
air.err.wallet,"Подпишите кошельком, давшим одобрение."
|
||||
pool.h,Сторонние пулы доходности (CRC)
|
||||
pool.none,Сейчас пулов нет.
|
||||
pool.col.name,Пул
|
||||
pool.col.rate,Ставка
|
||||
pool.col.reserve,Резерв
|
||||
pool.col.lock,Таймлок
|
||||
pool.col.audit,Аудит
|
||||
pool.col.mine,Вклад
|
||||
pool.yes,да
|
||||
pool.no,нет
|
||||
pool.pending,вывод
|
||||
pool.closed,(закрыт)
|
||||
pool.deposit,Депозит
|
||||
pool.withdraw,Вывод
|
||||
pool.withdraw.lock,Запросить вывод ({0} дн.)
|
||||
pool.err.cap,Превышен лимит пула; доступно: {0}.
|
||||
pool.err.none,Нет депозита.
|
||||
pool.sum.in,Депозит в {0}: {1} CRC
|
||||
pool.sum.out,Вывод {1} CRC из {0}
|
||||
pool.done.in,Внесено {0} CRC в {1}.
|
||||
pool.done.out,Выведено {0} CRC.
|
||||
pool.done.lock,"Запрошен вывод {0} CRC, поступление: день {1}."
|
||||
nightlog.scam.drain,{1} {2} из {0} списаны «{3}» через одобрение.
|
||||
nightlog.scam.rug,Пул доходности «{0}» совершил рагпул; {1} CRC из {2} пропали.
|
||||
nightlog.scam.dry,Пул доходности «{0}» исчерпал резерв и закрылся; {1} CRC возвращены на {2}.
|
||||
nightlog.scam.paid,Вывод из «{0}» поступил: на {2} зачислено {1} CRC.
|
||||
nightlog.scam.fakepay,Поддельный перевод: {0}
|
||||
nightlog.scam.sent,Отправленные на «безопасный» адрес «поддержки» {0} {1} достались мошенникам.
|
||||
coinpay.intro,Я заплачу в {0}; подтверждение в сети займёт немного времени.
|
||||
coinpay.intro.fake,"Я уже перевёл {0}, вот скриншот. Давай товар, я спешу."
|
||||
coinpay.fake.entry,"{0} забрал {1}, заявив, что заплатил {2} кредитов монетами; в сети такой транзакции нет."
|
||||
scam.support.name,Поддержка Poinbase
|
||||
scam.support.1,"Здравствуйте, служба поддержки Poinbase. Мы зафиксировали подозрительный вход в ваш аккаунт, он был помечен."
|
||||
scam.support.2,"Пожалуйста, переведите сегодня {0} CRC на безопасный адрес {1} для проверки; средства вернут сразу после неё."
|
||||
scam.support.3,"Иначе аккаунт будет заморожен навсегда. Мне пора, не забудьте перевести."
|
||||
predict.sold.caught,"Инсайдерская сделка раскрыта при продаже: ставка и прибыль конфискованы, зафиксировано мошенничество."
|
||||
predict.row.move," (прошлой ночью {0} {1})"
|
||||
predict.stats.h,История (ср. цена открытия / факт. частота)
|
||||
predict.stats.row,"{0}: рынков: {1}, ср. открытие {2}, сбылось {3}%"
|
||||
predict.kind.Event,События новостей
|
||||
predict.kind.Faction,Операции фракций
|
||||
predict.kind.Purity,Чистота воды
|
||||
predict.kind.Price,Цена PSC
|
||||
predict.kind.Gas,Газ
|
||||
predict.kind.Cra,Предупреждение CRA
|
||||
predict.kind.Era,Эра асик-майнеров
|
||||
nightlog.predict.move,Прогноз «{0}» изменился: {1} -> {2}
|
||||
nightlog.predict.why," ({0})"
|
||||
chart.empty,Дневной график {0}: истории пока нет; запись с сегодняшнего дня.
|
||||
chart.caption,"{0}, день Макс {2} Мин {3} Закр {4} ({5}%)"
|
||||
chart.legend,"<size=80%>зелёный — рост, красный — спад; жёлтая — 7-дн. MA; столбцы: серый — рынок / бирюзовый — вы</size>"
|
||||
chart.legend.thr,"<size=80%>зелёный — рост, красный — спад; жёлтая — 7-дн. MA; синий пунктир — порог</size>"
|
||||
news.story.serpico_rev.title,У Революционеров есть компромат на Службу безопасности
|
||||
news.story.serpico_rev.desc,"Сообщается, что Революционеры получили улики против коррупционеров в Службе безопасности. Из пула стейкинга передают: крупная сумма влита в резерв Революционеров, а SPARK укрепляется."
|
||||
news.story.serpico_bm.title,Чёрный рынок заключил негласную сделку
|
||||
news.story.serpico_bm.desc,"Внутренний документ Службы безопасности перешёл из рук в руки на Чёрном рынке. С тех пор расчёты в Даркнете заметно стабилизировались, а погашение CRT проходит без сбоев."
|
||||
news.story.serpico_sec.title,Служба безопасности начинает внутреннюю чистку
|
||||
news.story.serpico_sec.desc,"Служба безопасности объявила о масштабном расследовании внутренней коррупции и усилении контроля за денежными потоками. Poinbase ужесточает проверку вывода средств, а миксеры были названы напрямую."
|
||||
news.story.eleanor_leak.title,Утечка данных о селекции нутрифруктов
|
||||
news.story.eleanor_leak.desc,"Газета Нижнего уровня опубликовала данные исследования, позволяющего нутрифруктам снова давать семена; акции Пастель рухнули. Банк, хранящий средства Верхнего уровня, сообщил о безнадёжных долгах, а влияние Революционеров растёт."
|
||||
news.story.eleanor_return.title,Пастель возвращает украденные данные
|
||||
news.story.eleanor_return.desc,"Пастель подтвердила возврат похищенных данных исследований. Капитал Верхнего уровня вздохнул с облегчением, а рейтинг банка-кастодиана CRC был повышен."
|
||||
news.story.lun_arrested.title,Офицер Лунь арестован за злоупотребление полномочиями
|
||||
news.story.lun_arrested.desc,Служба безопасности на месте арестовала офицера Луня за злоупотребление полномочиями и пообещала жёстко пресекать нелегальную торговлю в течение следующих двух недель.
|
||||
tumbler.name,Тумблер
|
||||
tumbler.v1.1,"Привет. Слышал, здешний терминал подключён к моему миксеру."
|
||||
tumbler.v1.2,Эту штуку написал я. Меня зовут Тумблер.
|
||||
tumbler.v1.3,Он не трогает твой товар и не ведёт бухгалтерию. Он просто перемешивает монеты.
|
||||
tumbler.v1.4,"Проходил мимо. Хотел посмотреть, как выглядят мои пользователи."
|
||||
tumbler.v2.1,Времена настали неспокойные. Служба безопасности взялась за миксеры в сети.
|
||||
tumbler.v2.2,Они пометили несколько крупных адресов и вышли по ним на мой узел.
|
||||
tumbler.v2.3,"Если миксер отключится на пару дней, без паники. Монеты внутри не пропадут."
|
||||
tumbler.v3.1,"Они отключили мой узел. Рано или поздно они найдут, где я живу."
|
||||
tumbler.v3.2,У меня с собой ключ-накопитель с ключами подписи миксера.
|
||||
tumbler.v3.3,"Если он попадёт к Службе безопасности, они смогут восстановить историю всех пользователей. Твою тоже."
|
||||
tumbler.v3.ask,Можешь припрятать его на пару дней?
|
||||
tumbler.v3.choice.hide,[Взять ключ-накопитель и спрятать его]
|
||||
tumbler.v3.choice.report,"[Согласиться, а затем сообщить Службе безопасности]"
|
||||
tumbler.v3.choice.sell,[Взять ключ-накопитель и продать на Чёрном рынке]
|
||||
tumbler.v3.thanks1,Спасибо. Я вернусь за ним через несколько дней.
|
||||
tumbler.v3.thanks2,Не бросай на видном месте. Если найдут при обыске — нам обоим конец.
|
||||
tumbler.v3.report1,...Ладно. Я зайду позже.
|
||||
tumbler.v4.back.1,Я пришёл за ключом-накопителем.
|
||||
tumbler.v4.back.2,Узел перенесён на новое место. Служба безопасности найдёт его нескоро.
|
||||
tumbler.v4.back.3,Вот за хлопоты. С этого момента комиссии миксера для тебя вдвое ниже.
|
||||
tumbler.v4.lost.1,Где ключ-накопитель?
|
||||
tumbler.v4.lost.2,...Ты его потерял?
|
||||
tumbler.v4.lost.3,Забудь. Я что-нибудь придумаю.
|
||||
tumbler.v4.sold.1,Ты ведь продал ключ-накопитель Чёрному рынку.
|
||||
tumbler.v4.sold.2,"Теперь миксером заправляют они. Комиссии удвоились, а деньги пользователей могут исчезнуть в любой день."
|
||||
tumbler.v4.sold.3,Я этого не забуду.
|
||||
tumbler.v4.none.1,Забудь. Меня здесь не было.
|
||||
item.keydrive.name,Ключ-накопитель
|
||||
item.keydrive.desc,"Накопитель данных, оставленный Тумблером; содержит ключи подписи миксера. Контрабанда: обнаружение при обыске будет занесено в дело."
|
||||
mixer.closed,"Миксер закрыт и больше не принимает депозиты. Монеты, которые уже внутри, возвращаются в обычном порядке."
|
||||
news.tumbler.sanction.title,Служба безопасности изъяла узел миксера
|
||||
news.tumbler.sanction.desc,"Служба безопасности объявила об изъятии узла ончейн-миксера, заявив, что тот способствовал отмыванию денег. Сервис временно недоступен."
|
||||
news.tumbler.caught.title,Арестован оператор миксера
|
||||
news.tumbler.caught.desc,"Оператор миксера, известный как Тумблер, арестован на Нижнем уровне. Служба безопасности заявляет, что сервис микширования закрыт навсегда."
|
||||
news.tumbler.sold.title,Миксер сменил владельца
|
||||
news.tumbler.sold.desc,"По слухам, ключи подписи миксера с Нижнего уровня попали в руки Чёрного рынка, и комиссии тут же выросли. Пользователи опасаются за свои средства."
|
||||
nightlog.tumbler.gift,Тумблер забрал ключ-накопитель и оставил {0} CRT в знак благодарности (отправлено на {1}); комиссии миксера снижены вдвое.
|
||||
mixer.status.closed,Статус: закрыт
|
||||
yield.sub.pools,Доходные пулы
|
||||
yield.sub.mine,Запуск схемы
|
||||
pool.side.h,Депозит
|
||||
ponzi.early,Схемы Понци можно запускать со дня {0}.
|
||||
bpay.h,Оплата
|
||||
bpay.qty,Количество
|
||||
bpay.total,Итого (кредиты): {0}
|
||||
bpay.need,К оплате: {0} {1} баланс кошелька: {2}
|
||||
bpay.invoice,Создать счёт
|
||||
bpay.swap.h,Автообмен на {0}
|
||||
bpay.swap.none,В кошельке недостаточно других монет
|
||||
bpay.swap.need,"К оплате {0} {1}, включая проскальзывание {2}%"
|
||||
bpay.swap.btn,Обменять и оплатить
|
||||
bpay.swap.sum,"{0}: автообмен, к оплате {2} {1}, обмен на {3} перед заказом"
|
||||
bpay.back,Назад
|
||||
cart.fab,Корзина {0}
|
||||
cart.h,Корзина
|
||||
cart.empty,Корзина пуста.
|
||||
cart.added,Добавлено в корзину: {0}
|
||||
cart.back,Назад в магазин
|
||||
cart.done,Оплачено: {0} шт.
|
||||
cart.partial,Оплачено: {0} шт.; не удалось: {1} шт. (нет на складе или не хватает баланса).
|
||||
black.info.accepts,Принимает: {0}
|
||||
black.info.advance.yes,досрочная выплата принимается
|
||||
black.info.advance.no,без досрочной выплаты
|
||||
settings.section.ui,Интерфейс
|
||||
settings.section.story,Сюжет
|
||||
settings.section.difficulty,Сложность
|
||||
settings.terminal_size,Размер торгового терминала
|
||||
settings.terminal_size_desc,Размер окна в единицах интерфейса (ширина × высота). Применяется при следующем открытии терминала.
|
||||
settings.tumbler_story,Сюжет Тумблера
|
||||
settings.tumbler_story_desc,Визиты Тумблера и поручение с ключом-накопителем. При отключении новых визитов не будет; достигнутый прогресс сохраняется.
|
||||
settings.risk_scale,Множитель риска
|
||||
settings.risk_scale_desc,"Умножает вероятность мошенничества, рагпулов, отравления кошелька, подмены адреса и фишинга. Действует для всех сохранений."
|
||||
settings.mining_scale,Множитель добычи
|
||||
settings.mining_scale_desc,"Умножает награду за блок, получаемую майнинг-фермами. Действует для всех сохранений."
|
||||
gg.header,Торговая комиссия станции
|
||||
gg.p1.cap,Видеокарта
|
||||
gg.p1.makers,На станции распространены два производителя:\n\n - Probidia («PB»)\n - PMD («MD»)
|
||||
gg.p1.note,"Независимо от производителя стоимость карты зависит только от прайсовой цены настоящего чипа и его прочности: при полной прочности она равна прайсовой цене, при прочности 0 остаётся лишь {CardValueFloor:%}."
|
||||
gg.fan.h,Лопасти
|
||||
gg.fan.0,Чистые (цена прежняя)
|
||||
gg.fan.1,В пыли (-{CardFanDust:%})
|
||||
gg.fan.2,Скол (-{CardFanChipped:%})
|
||||
gg.fin.h,Контакты
|
||||
gg.fin.0,Блестящие (цена прежняя)
|
||||
gg.fin.1,Потускневшие (-{CardFingersDark:%})
|
||||
gg.fin.2,Окисленные (-{CardFingersOxidized:%})
|
||||
gg.brk.h,Планка
|
||||
gg.brk.0,Целая (цена прежняя)
|
||||
gg.brk.1,С царапинами (-{CardBracketScratch:%})
|
||||
gg.seal.h,Пломба
|
||||
gg.seal.0,Целая (цена прежняя)
|
||||
gg.seal.2,Отсутствует (-{CardSealMissing:%})
|
||||
gg.wear.note,"Лопасти, контакты и планка ухудшаются от ночного износа и только портятся со временем; пломба — постоянный признак. Состояние также влияет на хешрейт, износ и вероятность сгореть."
|
||||
gg.serial.h,Серийный номер
|
||||
gg.serial.cap,Обратная сторона (наклейка)
|
||||
gg.serial.pb,"Probidia («PB»)\n Допустимые коды заводов: 11, 12, 21, 34, 47"
|
||||
gg.serial.md,"PMD («MD»)\n Допустимые коды заводов: 13, 22, 35, 41, 58"
|
||||
gg.print.h,Маркировка сзади
|
||||
gg.print.0,Соответствует модели
|
||||
gg.print.1,Другая модель (подделка)
|
||||
gg.print.2,"Перепечатано, криво (подделка)"
|
||||
gg.point.h,Указание
|
||||
gg.ex.card,"Пример: {0}, прочность {1}%"
|
||||
gg.ex.base,Базовая стоимость: +{0}
|
||||
gg.ex.fan,Скол на лопасти: -{0}
|
||||
gg.ex.fin,Потускневшие контакты: -{0}
|
||||
gg.ex.seal,Нет пломбы: -{0}
|
||||
gg.ex.total,Итоговая стоимость: {0}
|
||||
gg.ex.note,Каждая скидка — доля базовой стоимости; скидки складываются и вычитаются.
|
||||
gg.ex.fan1,Лопасти в пыли: -{0}
|
||||
gg.ex.fin2,Окисленные контакты: -{0}
|
||||
gg.ex.brk,Царапины на планке: -{0}
|
||||
gg.ex.nodisc,Скидок нет: -0
|
||||
gg.ex.fake,"Указано {0}, реальный чип {1}: оценка по реальному чипу"
|
||||
gg.ex.claimed,Цена указанной модели: {0}
|
||||
gg.ex.gap,Разница с предложением: {0}
|
||||
gg.ex.h2,Пример оценки: подделка
|
||||
gg.ex.h3,Пример оценки: сильный износ
|
||||
gg.ex.h4,Пример оценки: лёгкий износ
|
||||
gg.ex.h5,Пример оценки: новая
|
||||
lbl.price,Цена по ярлыку: {0}
|
||||
lbl.row.count,Вентиляторы
|
||||
lbl.row.pin,Питание
|
||||
lbl.count.1,1 вентилятор
|
||||
lbl.count.2,2 вентилятора
|
||||
lbl.count.3,3 вентилятора
|
||||
lbl.pin.0,6-pin
|
||||
lbl.pin.1,8-pin
|
||||
lbl.pin.2,2×8-pin
|
||||
gg.p1.body,"Видеокарты — ключевой компонент любой майнинг-фермы и самый часто подделываемый товар на вторичном рынке.\nПодлинность карты определяют четыре признака: число вентиляторов, разъём питания, маркировка на обратной стороне и серийный номер. Подлинна только та карта, у которой все четыре признака соответствуют заявленной модели; любое одно несоответствие означает подделку.\nСтоимость карты зависит от модели настоящего чипа и от её состояния, а каждый след износа снижает цену.\n\nЭто руководство содержит все знания, необходимые для оценки видеокарты."
|
||||
gg.p2.h,Модели видеокарт
|
||||
gg.p2.body,Модель определяет число вентиляторов и разъём питания. Подделка — это чип низшей модели в корпусе высшей; её производительность и стоимость определяются настоящим чипом внутри.
|
||||
gg.tier.0,"RTX 60 / RX 70: 6-pin, 1 вент."
|
||||
gg.tier.1,"RTX 70 / RX 80: 8-pin, 2 вент."
|
||||
gg.tier.2,"RTX 80 / RX 800: 8-pin, 3 вент."
|
||||
gg.tier.3,"RTX 90 / RX 900: 2×8-pin, 3 вент."
|
||||
gg.count.h,Число вентиляторов
|
||||
gg.count.body,"Число вентиляторов определяется моделью: один вентилятор у RTX 60 и RX 70, два у RTX 70 и RX 80, три у RTX 80, RTX 90, RX 800 и RX 900.\nЧисло вентиляторов, не соответствующее заявленной модели, означает подделку."
|
||||
gg.pin.h,Разъём питания
|
||||
gg.pin.body,"Разъём питания тоже определяется моделью: 6-pin у RTX 60 и RX 70, 8-pin у RTX 70, RTX 80, RX 80 и RX 800, 2×8-pin у RTX 90 и RX 900.\nРазъём питания, не соответствующий заявленной модели, означает подделку."
|
||||
gg.serial.body,"Серийный номер наклеен на обратной стороне карты и состоит из префикса, кода модели, дефиса, двузначного кода завода, дефиса и четырёхзначного порядкового номера, например PB2-21-6251."
|
||||
gg.serial.rule,"Коды модели от 1 до 4 соответствуют RTX 60 / RX 70, RTX 70 / RX 80, RTX 80 / RX 800 и RTX 90 / RX 900.\nКод модели, не соответствующий модели (наклейка от исходного чипа), либо недопустимый код завода или длина (наклейка добавлена позже) означает подделку. Код завода служит только для проверки подлинности и на цену не влияет."
|
||||
gg.print.note,"Карта подлинна, только если число вентиляторов, разъём питания, маркировка и серийный номер соответствуют модели. У подделки не совпадает хотя бы один признак, но остальные могут быть выполнены правильно, поэтому проверять нужно каждый."
|
||||
gg.point.body,"Осмотр выполняется с помощью лупы. На панели меток кнопка «Указать модель» есть только у строки модели; четыре строки под ней (вентиляторы, питание, маркировка сзади, серийный номер) доступны только для просмотра, а у каждой из четырёх строк состояния — лопасти, контакты, планка, пломба — своя кнопка «Указать».\nЕсли указать на скрытую проблему состояния, строка меняется на реальное состояние, а цена снижается на разницу; если указать на то, что соответствует действительности, другая сторона отказывается, и репутация страдает.\nЕсли число вентиляторов, питание, маркировка сзади или серийный номер не соответствуют заявленной модели, укажите модель: карта признаётся подделкой, модель меняется на настоящий чип, а цена пересчитывается по этому чипу.\n\nКарты, которые приносят клиенты гильдии оценщиков, обрабатываются так же: после указания проблем оценка меняется, пока не будет названа правильная стоимость."
|
||||
gg.ex.serial,Серийный номер: {0}
|
||||
gg.ex.h,"Пример оценки: скол на лопасти, потускневшие контакты, нет пломбы"
|
||||
rig.label.status,Статус
|
||||
rig.st.cards,Видеокарты
|
||||
rig.st.power,Расход
|
||||
rig.st.hash,Хешрейт
|
||||
rig.st.kj,{0} кДж/день
|
||||
lbl.point.model,Указать модель
|
||||
col.crcprice,Цена в CRC
|
||||
swap.pay,Отдаю
|
||||
swap.get,Получаю
|
||||
swap.preview,"Около {0} {1} пулов: {2}, потери {3}%"
|
||||
swap.go,Обменять
|
||||
swap.same,Монеты оплаты и получения должны различаться.
|
||||
mint.need,Нужно {0} CRC и {1} SPARK
|
||||
mint.reserve,Покрытие резерва {0}% Залог {1}%
|
||||
mint.queue,Очередь
|
||||
mint.order,"{0} {1} CRA, день {2}"
|
||||
stake.coin,Монета для вклада
|
||||
stake.sum.via,Обменять {0} {1} → около {2} CRA и внести в стейкинг
|
||||
nightlog.cra.lost,Эмитент не ответил: заявка ({1}) на {0} CRA потеряна.
|
||||
news.crawarn.desc,"Кто-то пересчитывает резерв Революционеров, и CRA в стейкинге могут не выкупить полностью. Разблокировка занимает четыре дня; кое-кто говорит, что пора действовать."
|
||||
news.cralow.desc,"Покрытие резерва тает, и Революционеры снизили ставку по стейкингу CRA до малой доли."
|
||||
poin.sub.funds,Средства
|
||||
funds.receive,Ввод
|
||||
funds.send,Вывод
|
||||
funds.bank,Банковский счёт
|
||||
funds.wallet,Кошелёк
|
||||
funds.to,Адрес получателя
|
||||
funds.go,Отправить
|
||||
funds.sending,Отправка {0} {1} на {2}
|
||||
funds.confirm,Подтверждение {0}/{1}
|
||||
funds.done,{0} {1} поступили в {2}.
|
||||
funds.done.void,"{0} {1} отправлены; у адреса нет владельца, монеты потеряны."
|
||||
funds.err.addr,Неверный адрес.
|
||||
funds.err.self,Это адрес пополнения Poinbase.
|
||||
funds.err.known,Этот адрес принимает только оплату по счёту.
|
||||
funds.err.fee,Сумма не покрывает комиссию за газ.
|
||||
wallets.sub.explorer,Обозреватель
|
||||
explorer.search,Адрес
|
||||
explorer.all,Последние
|
||||
explorer.none,Переводов нет.
|
||||
explorer.col.block,Блок
|
||||
explorer.col.amount,Сумма
|
||||
explorer.mixer,Миксер
|
||||
cra.mint,Минт
|
||||
cra.burn,Сжигание
|
||||
mint.h,Официальный минт (CRC + SPARK)
|
||||
mint.sum.in,Минт {0} CRA за {1} CRC и {2} SPARK ({3}–{4} дн.)
|
||||
mint.sum.out,Сжигание {0} CRA в обмен на CRC и SPARK ({1} дн.)
|
||||
mint.done.in,Заявка на минт подана; срок — день {0}.
|
||||
mint.done.out,Заявка на сжигание подана; срок — день {0}.
|
||||
nightlog.cra.minted,"Создано {0} CRA, внесено в стейкинг ({1})."
|
||||
nightlog.cra.burned,"Сожжено {0} CRA: +{1} CRC, +{2} SPARK ({3})."
|
||||
predict.clue.subsidy,Резерв {0}%; при нуле предупреждение неизбежно
|
||||
air.noapprove,без доступа к токенам
|
||||
tab.gray,Серая сеть
|
||||
wallets.sub.list,Список
|
||||
entry.web3.l1,Децентрализованная торговля и доходность
|
||||
entry.mining.l1,Состояние ферм и ночной доход
|
||||
entry.gray.l1,Миксер и магазин
|
||||
entry.wallets.l1,Аппаратные кошельки и обозреватель
|
||||
entry.wallets.l2,Кошельки {0} / {1}
|
||||
black.sell.add,Добавить товары
|
||||
black.sell.back,Назад к витрине
|
||||
black.sell.kinds,Выставлено {0}/{1} видов
|
||||
black.sell.have,Выставлено: {0}
|
||||
black.sell.coins,Принимаемые монеты
|
||||
black.sell.off,Снять
|
||||
black.sell.off.n,Снять ×{0}
|
||||
black.sell.nocoin,Нужно принимать хотя бы одну монету.
|
||||
black.sell.empty,Ничего не выставлено.
|
||||
black.sell.delisted,Снято: {0}; товар вернулся на склад.
|
||||
black.sell.partial,"Выставлено: {0}, не удалось выставить: {1}."
|
||||
black.sell.limit.stack,Не более {0} единиц каждого товара.
|
||||
black.sell.limit.kinds,Одновременно можно выставить не более {0} видов.
|
||||
shelf.fab,Полка {0}
|
||||
delist.fab,Подтвердить снятие {0}
|
||||
black.fee.h,Готово к выставлению
|
||||
black.fee.line,{0} ×{1} · цена {2} ({3})
|
||||
black.fee.total,Комиссия за размещение {0}
|
||||
black.fee.sum,Комиссия за размещение ({0} шт.)
|
||||
black.sale.Sold,"продано, выплата на день {0} в {1}"
|
||||
explorer.col.day,День
|
||||
explorer.day,День {0}
|
||||
explorer.pool,пул RatDigg
|
||||
explorer.desk,обменник Ponero
|
||||
black.fee.pay,Оплата комиссии за размещение
|
||||
explorer.col.from,От
|
||||
explorer.col.to,Кому
|
||||
rig.st.cond,Состояние
|
||||
asic.st.dead,Сгорел
|
||||
perp.preview,Номинал {0} ожид. ср. цена {1} (проскальзывание {2}%)
|
||||
perp.sim.close,Закрытие номинал {0} ожид. ср. цена {1} (проскальзывание {2}%)
|
||||
perp.sim.close2,Комиссия {0} вернётся около {1} CRC (П/У {2})
|
||||
trade.sim.sell,Продажа даст около {0} {1} ср. {2} проскальзывание {3}%
|
||||
trade.sim.buy,Покупка обойдётся примерно в {0} {1} ср. {2} проскальзывание {3}%
|
||||
trade.amount.unit,Количество ({0})
|
||||
trade.fee,Комиссия {0}%
|
||||
trade.sim.thin,Превышает ликвидность пула
|
||||
news.wipe.down.title,"{0} упал на {1}% за день, ликвидировано трейдеров: {2}"
|
||||
news.wipe.down.desc,За прошедшие сутки ликвидировано {1} длинных позиций по бессрочным контрактам {0} на общую сумму {2} кредитов. Страховой фонд Poinbase составляет {3} кредитов.
|
||||
news.wipe.up.title,"{0} вырос на {1}% за день, ликвидировано трейдеров: {2}"
|
||||
news.wipe.up.desc,За прошедшие сутки ликвидировано {1} коротких позиций по бессрочным контрактам {0} на общую сумму {2} кредитов. Страховой фонд Poinbase составляет {3} кредитов.
|
||||
hot.name,Продавец
|
||||
hot.intro.CRT,"Сейчас неспокойно, а этот CRT жжёт руки. Мне нужны наличные, быстро."
|
||||
hot.intro.PSC,"Кошелёк одной майнинг-фермы прошлой ночью сменил владельца. PSC теперь у меня, и я беру только наличные."
|
||||
hot.intro.PONERO,"Выкуп, в Ponero. Никто не отследит. Только наличные."
|
||||
hot.offer,"{0} {1}, по сегодняшнему курсу это {2}. Дайте мне {3} наличными, и монеты сразу ваши."
|
||||
hot.choice.yes,Взять
|
||||
hot.choice.no,Отказаться
|
||||
hot.say.yes,По рукам.
|
||||
hot.say.no,Я в это не полезу.
|
||||
hot.done,Монеты отправлены. Мы не встречались.
|
||||
hot.refused,Найдутся другие.
|
||||
hot.nocash,Даже наличных нет? Забудьте.
|
||||
hot.nowallet,"Кошелёк не подключён, куда слать монеты? Забудьте."
|
||||
hot.sting,"Не двигаться. Служба безопасности. Скупка краденых средств: наличные изъяты, это пойдёт в ваше досье."
|
||||
hw.err.poinbase,Poinbase не принимает {0}.
|
||||
@@ -1,33 +1,30 @@
|
||||
# Probably Decentralized 本地化表:简体中文(zh)
|
||||
upgrade.tab,Web3
|
||||
upgrade.title,Web3 治理社区
|
||||
upgrade.desc,"成员可获得一台交易终端、一个矿架和一张 RZX 50 显卡。终端用于查看钱包,并在 Poinbase 交易所交易。更多显卡和矿架由杰克逊博士出售。"
|
||||
upgrade.desc,成员可获得一台交易终端、一个硬件钱包、一个矿架、一张 RTX 60 显卡和一本显卡鉴定指南。终端里有银行、Poinbase 交易所、Web3 页、挖矿页和钱包页。更多显卡和矿架由杰克逊博士出售。
|
||||
item.terminal.name,交易终端
|
||||
item.terminal.desc,钱包、Poinbase 交易所与夜间挖矿报告。
|
||||
item.rig.name,矿架
|
||||
item.rig.desc,最多装 {0} 张显卡。算力 {1} MH/s。耗电 {2} kJ/天。
|
||||
rig.label.modules,模块
|
||||
item.rig.modules,模块:算力 {0},耗电 {1},损耗 {2}。
|
||||
rig.label.upgrade,升级槽位
|
||||
item.rig.next,第 {0} 槽:投入{1}({2}/{3})。
|
||||
item.rig.next,"第 {0} 槽:把{1}拖到矿架上({2}/{3})。"
|
||||
mat.common_electronic,普通电子元件
|
||||
mat.rare_electronic,稀有电子元件
|
||||
rig.label.cards,显卡
|
||||
item.gpu.name,{0} {1}
|
||||
item.gpu.desc,算力 {0} MH/s。耗电 {1} kJ/天。健康度 {2}%。
|
||||
item.gpu.desc,标称算力 {0} MH/s。标称耗电 {1} kJ/天。成色 {2}。
|
||||
item.gpu.burnt.name,烧毁的 {0} {1}
|
||||
item.gpu.burnt.desc,此显卡已无法工作。
|
||||
term.title,交易终端
|
||||
tab.wallet,钱包
|
||||
tab.trade,交易
|
||||
tab.report,报告
|
||||
wallet.line,{0}:{1}(约 {2} 信用点)
|
||||
wallet.empty,钱包为空。
|
||||
wallet.total,总值:{0} 信用点
|
||||
wallet.taint,污点:{0} 信用点
|
||||
trade.amount,数量
|
||||
trade.hint,买入按计价币的数量支付;卖出按所交易币的数量卖出。
|
||||
trade.deposit,存入信用点(换成 CRC)
|
||||
trade.withdraw,提取 CRC(换成信用点)
|
||||
trade.deposit,存入信用点
|
||||
trade.withdraw,提取 CRC
|
||||
trade.pair,{0}/{1}({2})
|
||||
trade.price,价格 {0}
|
||||
trade.buy,买入
|
||||
@@ -35,16 +32,16 @@ trade.sell,卖出
|
||||
venue.Exchange,Poinbase
|
||||
venue.Dex,DEX
|
||||
venue.Darknet,暗网
|
||||
msg.amount,请输入数量。
|
||||
msg.amount,未输入数量。
|
||||
msg.balance,余额不足。
|
||||
msg.trade,支付 {0} {1},得到 {2} {3}。
|
||||
msg.deposit,已存入 {0} 信用点,换成 CRC。
|
||||
msg.trade,支付 {0} {1},获得 {2} {3}。
|
||||
msg.deposit,已存入 {0} 信用点,兑换为 CRC。
|
||||
msg.cashout,到账 {0} 信用点。税 {1} 信用点。
|
||||
msg.aml_light,合规审查:{0} 信用点的污点资金被扣留。
|
||||
msg.aml_heavy,合规审查:{0} 信用点的污点资金被没收,并已上报安保部。
|
||||
msg.aml_heavy,合规审查:{0} 信用点的污点资金被没收,并已上报治安部。
|
||||
report.none,暂无挖矿报告。
|
||||
report.day,第 {0} 天夜间
|
||||
report.rigs,有电的矿架:{0} / {1}
|
||||
report.rigs,供电矿架:{0} / {1}
|
||||
report.hash,算力:{0} MH/s(全网 {1} MH/s)
|
||||
report.mined,挖出:{0} PSC(约 {1} 信用点)
|
||||
report.energy,耗电:{0} kJ
|
||||
@@ -52,8 +49,931 @@ report.burnt,烧毁的显卡:{0}
|
||||
report.price,PSC 价格:{0} 信用点
|
||||
nightlog.mined,矿架挖出 {0} PSC。
|
||||
nightlog.burnt,一张 {0} 烧毁了。
|
||||
nightlog.unpowered,{0} 个矿架没有电。
|
||||
coinpay.line,成交,{0} {1}。
|
||||
nightlog.coinpay,代币支付共结算 {0} 信用点,已兑换并存入热钱包。
|
||||
nightlog.unpowered,{0} 台矿架或矿机未通电。
|
||||
news.open.title,Poinbase 上架 PSC
|
||||
news.open.desc,上层交易所 Poinbase 上架 PSC/CRC 交易对。全站显卡需求上升。
|
||||
news.halving.title,PSC 出块奖励减半
|
||||
news.halving.desc,矿工每晚获得的币减半。
|
||||
appraisal.gpu,"显卡"
|
||||
dealer.name,"二手货贩子"
|
||||
dealer.line1.1,"矿场清仓的卡,成色都在名字后面标着。"
|
||||
dealer.line1.2,"几张挖过的卡,便宜出。"
|
||||
dealer.line1.3,"路上收来的货,一手价。"
|
||||
dealer.line2.1,"自己看,背面也翻过来看。"
|
||||
dealer.line2.2,"不保修,看好了再拿。"
|
||||
dealer.line2.3,"要的话价钱好商量。"
|
||||
inspect.flip.back,"翻到背面"
|
||||
inspect.flip.front,"翻到正面"
|
||||
item.gpu.grade.1,"接近全新"
|
||||
item.gpu.grade.2,"成色尚可"
|
||||
item.gpu.grade.3,"明显旧了"
|
||||
item.gpu.grade.4,"磨损严重"
|
||||
point.none.1,"没毛病,你看错了吧。"
|
||||
point.none.2,"这儿哪有问题?不买别瞎说。"
|
||||
point.worn.1,"……行,这点毛病是有,算你便宜点。"
|
||||
point.worn.2,"眼睛挺毒。好吧,这个价。"
|
||||
point.fake.1,"……被你看出来了。是翻新的货,按真的价给你。"
|
||||
point.fake.2,"啧,不是原装的。那就按芯片本来的价吧。"
|
||||
lbl.fan.0,"叶片干净"
|
||||
lbl.fan.1,"叶片积灰"
|
||||
lbl.fan.2,"叶片缺角"
|
||||
lbl.fingers.0,"光亮"
|
||||
lbl.fingers.1,"发暗"
|
||||
lbl.fingers.2,"氧化发绿"
|
||||
lbl.print.0,"与型号一致"
|
||||
lbl.print.1,"印着另一个型号"
|
||||
lbl.print.2,"重印过,字歪"
|
||||
lbl.said,"(卖家说:{0})"
|
||||
lbl.point,"指出"
|
||||
lbl.edit,"改"
|
||||
cust.fake.1,"这不是它标的那块。你拿假货糊弄我?"
|
||||
cust.fake.2,"型号对不上,里面的芯片根本不是这个。"
|
||||
cust.worn.1,"跟你写的不一样,毛病你没说。"
|
||||
cust.worn.2,"标签上的成色是假的吧,这个价我不要。"
|
||||
lbl.row.fan,"叶片"
|
||||
lbl.row.fingers,"金手指"
|
||||
lbl.row.bracket,"挡板"
|
||||
lbl.row.print,"背面丝印"
|
||||
lbl.row.serial,"序列号"
|
||||
lbl.row.seal,"封条"
|
||||
lbl.bracket.0,"完好"
|
||||
lbl.bracket.1,"有划痕"
|
||||
lbl.serial.0,"合规"
|
||||
lbl.serial.1,"工厂码或位数不合规"
|
||||
lbl.serial.2,"型号码不符"
|
||||
lbl.seal.0,"完好"
|
||||
lbl.seal.2,"已缺失"
|
||||
item.guide.name,显卡鉴定指南
|
||||
item.guide.desc,鉴定显卡真伪与价值的指南。
|
||||
lbl.row.spec,"型号"
|
||||
news.prehalving.title,"PSC 即将减半"
|
||||
news.prehalving.desc,"三天后矿工每晚获得的币减半。持币者预期币价上行。"
|
||||
tab.home,"首页"
|
||||
tab.bank,"银行"
|
||||
tab.poinbase,"Poinbase"
|
||||
tab.web3,"Web3"
|
||||
home.enter,"进入"
|
||||
home.open,打开
|
||||
home.summary,"信用点 {0} | 链上资产约 {1} 信用点"
|
||||
home.lastnight,第 {0} 天夜间:挖出 {1} PSC,{2} / {3} 台矿架通电
|
||||
entry.bank,"银行"
|
||||
entry.bank.l1,"信用点存取、房租"
|
||||
entry.bank.l2,"信用点 {0}"
|
||||
entry.poinbase,"Poinbase"
|
||||
entry.poinbase.l1,"合规交易所"
|
||||
entry.poinbase.l2,"PSC {0} 信用点"
|
||||
entry.web3,"Web3"
|
||||
entry.web3.l2,"约 {0} 信用点"
|
||||
entry.help,帮助
|
||||
entry.help.l1,Web3 手册
|
||||
bank.cash,"信用点:{0}"
|
||||
bank.rent,"房租:{0} 信用点,{1} 天后支付"
|
||||
bank.crc,"Poinbase 账户(CRC):{0}"
|
||||
poin.account,"Poinbase 账户:CRC {0},PSC {1}"
|
||||
avg.line,"{0} 买入均价:{1} 信用点"
|
||||
avg.short,"买入均价 {0}"
|
||||
avg.none,"—"
|
||||
col.asset,"币种"
|
||||
col.amount,"数量"
|
||||
col.value,"估值"
|
||||
col.avg,"买入均价"
|
||||
bank.cash.k,"信用点"
|
||||
bank.rent.k,"房租"
|
||||
bank.rent.v,"{0},{1} 天后支付"
|
||||
bank.crc.k,"Poinbase 账户(CRC)"
|
||||
poin.account.h,"Poinbase 账户"
|
||||
trade.h,"交易"
|
||||
web3.wallet.h,"链上钱包"
|
||||
stable.ok,"锚定正常"
|
||||
stable.depeg,"脱锚"
|
||||
stable.warn,"预兆:储备覆盖率告急"
|
||||
stable.spiral,"崩盘中"
|
||||
aml.taint,"账户污点比例:{0}%"
|
||||
mixer.h,混币器
|
||||
mixer.ok,状态:运行正常
|
||||
mixer.sanctioned,状态:已被制裁(还有 {0} 天),此期间提出的币视为被标记。
|
||||
mixer.pending,在途存入
|
||||
mixer.none,暂无在途存入。
|
||||
mixer.col.taint,污点
|
||||
mixer.col.ready,到期
|
||||
mixer.day,第 {0} 天
|
||||
mixer.deposit,存入
|
||||
mixer.balance,余额:{1} {0}
|
||||
mixer.rounds,轮数
|
||||
mixer.preview,"预计提回 {0} {1},污点约降低 {2}%,第 {3} 天到期。"
|
||||
mixer.go,存入混币器
|
||||
mixer.min,存入价值不得低于 {0} 信用点。
|
||||
mixer.done,已存入 {0} {1},第 {2} 天提回。
|
||||
mixer.upgrade.title,混币器
|
||||
mixer.upgrade.desc,"解锁终端灰网页里的混币器:把带污点的币存进去,几天后提回,污点降低。出金审查对刚从混币器出来的币更严格;镇压期间混币器可能被制裁,期间提出的币会被标记。"
|
||||
news.sanction.title,混币器被列入制裁名单
|
||||
news.sanction.desc,"安保部门宣布制裁一批混币服务。此后几天从混币器提出的资金将被视为可疑。"
|
||||
nightlog.mixer,混币器提回 {0} {1},污点 {2} → {3}。
|
||||
nightlog.mixer_flag,(制裁期间提出,地址被标记)
|
||||
nightlog.mixer_rug,混币器的运营者卷款跑路了:{0} {1} 没有提回。
|
||||
web3.sub.trade,交易
|
||||
gray.sub.mixer,混币器
|
||||
msg.frozen,代币处于冻结状态,到期前无法使用。
|
||||
wallet.frozen,"{0} 冻结 {1},第 {2} 天解冻"
|
||||
nightlog.crt_freeze,镇压期间黑市移交地址清单:{0} CRT 已被冻结,将于第 {1} 天解冻。
|
||||
nightlog.thaw,冻结的 {0} {1} 已解冻。
|
||||
news.crtfreeze.title,黑市配合镇压冻结部分 CRT 地址
|
||||
news.crtfreeze.desc,"传闻黑市为换取放行,向安保交出了一批 CRT 地址。声望低的持有者更容易被冻结。"
|
||||
black.upgrade.title,Web3 商店
|
||||
black.upgrade.desc,"解锁终端灰网页里的商店:黑市派系在链上的实体。货架上每周上一批违禁品,偶尔有高科技物品和显卡(要加价);可以直接买现货,也可以下订单等快递员上门。只收币(PSC、CRT、CRA、Ponero),脏币也收。需要黑市声望,镇压期间下线。"
|
||||
black.offline,镇压期间,商店的链上入口已经下线。
|
||||
black.closed,黑市声望需达到 {0}(当前 {1})。
|
||||
black.sub.buy,买货
|
||||
black.shop.h,现货柜台
|
||||
black.rep,"黑市声望 {0}"
|
||||
black.empty,本周商品已售罄。
|
||||
black.offer,"{0} ×{1} {2} 信用点等值"
|
||||
black.buy,购买
|
||||
black.bought,成交:{0} 已存入储藏区。
|
||||
black.pay.h,付款
|
||||
black.desk.h,Ponero 兑换处
|
||||
black.desk.left,今日剩余兑换额度:{0}(上限 {1})
|
||||
black.desk.price,"Ponero 价格:{0}"
|
||||
black.desk.swap,兑换
|
||||
black.desk.in,兑入 Ponero
|
||||
black.desk.out,兑出 Ponero
|
||||
black.desk.go,兑换
|
||||
black.desk.fail,兑换失败:余额不足、超出限额或数量无效。
|
||||
black.sub.orders,订单
|
||||
black.rugged,"平台出事了,入口关闭,还要 {0} 天才会有人重新开张。"
|
||||
black.seller,"成交 {1},好评 {2}%"
|
||||
black.orders.h,订单目录
|
||||
black.order,下单
|
||||
black.mode.Escrow,托管
|
||||
black.mode.Advance,提前放款
|
||||
black.ordered,"已下单:{0},预计第 {1} 天到。"
|
||||
black.mine.h,我的订单
|
||||
black.mine.none,暂无订单。
|
||||
black.mine.line,"{0}({1},{2}):{3},第 {4} 天"
|
||||
black.state.Pending,在途
|
||||
black.state.Ready,到货
|
||||
black.state.Done,已取
|
||||
black.state.Refunded.scam,卖家跑路,已退款
|
||||
black.state.Lost.scam,卖家跑路,钱没了
|
||||
black.state.Lost.rug,平台跑路,钱没了
|
||||
black.state.Lost.intercept,被截获
|
||||
black.forum.h,论坛情报
|
||||
black.forum.quiet,最近很安静。
|
||||
black.forum.scam,"有人说 {0} 收了钱不发货。"
|
||||
black.forum.rug,"最近提币变慢了,全场还在搞促销,投诉帖被删了不少。"
|
||||
nightlog.bm.scam_refund,商店:卖家 {0} 跑路了,{1} 的托管款已退回。
|
||||
nightlog.bm.scam_loss,商店:卖家 {0} 拿了提前放款的钱跑路,{1} 没有了({2} 信用点等值)。
|
||||
nightlog.bm.intercept,商店:{0} 的包裹被截获,{1} 信用点等值的货款没了。
|
||||
nightlog.bm.rug,商店:平台跑路,{0} 的在途款项({1})归零。
|
||||
nightlog.bm.reopen,商店:有人在老地方重新开张了。
|
||||
news.bmrug.title,黑市平台跑路
|
||||
news.bmrug.desc,"黑市的链上入口一夜之间下线,托管和提前放款的资金全部清零。几天后会有新的入口。"
|
||||
courier.name,快递员
|
||||
courier.line1.1,"东西到了。"
|
||||
courier.line1.2,"有你的包裹。"
|
||||
courier.line2.1,"别问我里面是什么,我也不想知道。"
|
||||
courier.line2.2,"货放这儿了,我走了。"
|
||||
gray.sub.black,商店
|
||||
black.stock,"剩 {0} 件"
|
||||
black.price,"{0} 信用点等值"
|
||||
black.noadvance,不接受提前放款
|
||||
black.kind.gpu,"显卡 成色 {0}%"
|
||||
black.kind.Contraband.1,违禁品(低)
|
||||
black.kind.Contraband.2,违禁品(中)
|
||||
black.kind.Contraband.3,违禁品(高)
|
||||
black.kind.Tech,高科技物品(加价)
|
||||
nightlog.bm.ready,商店:{0} 到货,开店后会有快递员上门。
|
||||
guide.web3.title,Web3 手册
|
||||
guide.web3.text,"银行与交易:银行页只读,显示现金、房租和 Poinbase 账户里的 CRC。Poinbase 的资金页管入金和出金,先选币种:CRC 可以走银行账户或钱包,其他币只能走钱包。从银行入金把信用点换成 Poinbase 账户里的 CRC;出金到银行把 CRC 换回信用点,要过合规审查,审查看 Poinbase 账户的污点。出金到钱包要填收款地址,等几次确认才到账,Gas 费固定按普通档、从转出的币里扣;地址格式或校验位不对会被拒绝,格式对但没人用的地址,币转过去就没了。¶交易:PSC 全称 Probably Stolen Coin,是显卡和矿机挖出的币。Poinbase 现货有 PSC/CRC 和 SPARK/CRC 两个交易对,跟着行情图选中的币切换。买入和卖出都填所交易币的数量,预览显示要付或能得到的计价币,均价含手续费,滑点不含。¶Web3 交易页可以任选两种币互换,实际都经 CRC 中转:CRC 在一端走一个池,否则走两个池,付两次手续费、滑点叠加,预览里会显示得到的数量、经过的池数和损耗。稳定币之间(CRT、CRA 对 CRC)走稳定币池:手续费 {StableFee:%},挂钩附近几乎没有滑点;脱锚时流动性变差,崩盘时流动性被撤走,滑点急剧变大。§硬件钱包:链上的币放在 PLEDGER 硬件钱包里,每个钱包的余额和污点分别计算。钱包是一件物品,拖到交易终端上加载;在终端的钱包页打开,在终端右上角连接或断开。Web3 页的交易和灰网页的商店、混币器用已连接的钱包,没有钱包或没有连接时只能看,余额都是 0;用币付款的顾客也进已连接的钱包。¶付款(商店、混币器、Ponero 兑换处、上架费)先在终端开账单,再在钱包里手输收款地址、按住 ✓ 签名;地址末尾两位是校验位,输错一位多半会被拦下,偶尔碰巧合法,币就转进了没人用的地址。DEX 兑换也要在钱包上签名。¶Poinbase 是托管账户,入金要从钱包转到它的充值地址(只收 PSC、CRC、SPARK;黑市的 CRT、革命军的 CRA 合规交易所不收,往充值地址转会被钱包拦下),出金在 Poinbase 的资金页发起。钱包页的浏览器可以按地址查转账记录,只显示真实发生的转账:你的钱包的每一笔进出(转账、DEX 兑换和其他合约调用、矿机收益、出金、别人转来的币);Ponero 是隐私币,不显示。更多硬件钱包向杰克逊博士购买,拖到交易终端上添加,最多 {WalletMax} 个;商店里也有更便宜的。不要的钱包可以在钱包页销毁,里面的币永久丢失,之后发到这个地址的币也丢了。¶转账要付 Gas 费,分慢、普通、快三档,Gas 价格大约一周一个起落;网络拥堵时 Gas 费变贵,慢档可能被挤出内存池。转账前核对完整地址。§质押:把 CRA 质押进革命军质押池每天有日息,利息并入本金;取出要先申请,等四天才到账,等待期间没有利息,也不能提前拿。CRA 是部分抵押的:每份 CRA 由革命军持有的 CRC 储备和平衡代币 SPARK 共同支撑,储备覆盖率和抵押率显示在质押页。质押利息以没有抵押的新 CRA 付出,会稀释储备覆盖率,质押的人越多稀释越快;覆盖率太低革命军会降息。革命军有时会挪用储备,先有风声,那是预兆;挪用后覆盖率跌破 {CraCrashRatio:%} 就崩盘:三天内 CRA 归零,四天的解锁期来不及;没跌破只是折价,劫掠上层带来的资金会慢慢把储备补回来。¶官方铸造:存入 CRC 和 SPARK(比例按当前抵押率,界面预览需要多少)铸造 CRA,排 {CraMintDaysMin}~{CraMintDaysMax} 天,铸出的 CRA 直接进质押;销毁把 CRA 换回 CRC 和 SPARK,等待和解锁期一样长,储备不足时 CRC 份额按覆盖率打折。排队的铸造和销毁,官方可能整笔不兑现:每晚的概率是 CRA 价格低于 1 的幅度乘以 {CraRugPerDepeg},价格不低于 1 就不会。¶质押可以存 CRA、CRC、CRT、SPARK:后三种先在二级市场按市价换成 CRA(经 CRC 中转,付手续费和滑点)再质押。SPARK 价格波动很大,崩盘时会跟着暴跌。质押、铸造、销毁都是合约调用,要在钱包上签名。§矿机:RatDigg 矿机(M1 / M2 / M3)是独立的机器,算力比显卡大得多、耗电更省,要放电池才挖,可以放模块,不占矿架槽位;只在商店的矿机商那里有,要黑市声望(M1 {AsicRepM1}、M2 {AsicRepM2}、M3 {AsicRepM3}),偶尔有二手的。烧毁后须按顺序把电子元件拖到它身上修复,修复后健康降低 {AsicRepairHealthCut}。第 {EraMin} 到 {EraMax} 天之间会有一次""矿机时代"",提前几天上报纸预告,之后大矿场的耗电成本砍半,全网算力涨上去,显卡矿工的收益被摊薄,低档显卡Line truncated
|
||||
courier.odd1,……东西到了。
|
||||
courier.odd2,"(他的手一直放在口袋里)在这儿签个字。"
|
||||
courier.sign,签收
|
||||
courier.refuse,拒签
|
||||
courier.signed,"好。别动,治安部的。"
|
||||
courier.refused,"……那就算了。"
|
||||
black.state.Lost.seized,被查封
|
||||
black.state.Lost.refused,拒签
|
||||
black.forum.easy,"最近太顺了,卖家发货比平时都快,还多了几个没见过的新号。"
|
||||
black.forum.busted,"有人说 {0} 被抓了,他的订单记录还在。"
|
||||
nightlog.bm.trap.honeypot,商店:平台曾被执法接管,你买的 {0} 被追查,记罪证 {1}。
|
||||
nightlog.bm.trap.seller,商店:卖家落网,他留存的订单记录连累了你:{0},记罪证 {1}。
|
||||
tab.mining,挖矿
|
||||
courier.sign.say,签收。
|
||||
courier.refuse.say,不收,退回去。
|
||||
black.forum.busted_buyer,"有人说最近一批买家被抓了,成交记录还在平台上。"
|
||||
nightlog.bm.sale_sold,商店:你上架的 {0} 卖出了,货款 {1},第 {2} 天放款。
|
||||
nightlog.bm.sale_paid,商店:{0} 的货款 {1} 到账(CRT),其中污点 {2}。
|
||||
nightlog.bm.sale_fake,商店:买家看穿了 {0} 是假卡,退了货,你的好评下降。
|
||||
nightlog.bm.sale_rug,商店:平台跑路,你的 {0} 和货款({1})没了。
|
||||
black.sub.sell,卖货
|
||||
black.sell.h,出售
|
||||
black.sell.mult,标价倍率
|
||||
black.sell.none,储藏区无符合上架条件的物品。
|
||||
black.sell.rating,"好评 {0}%"
|
||||
black.mine.sale,"{0} 参考 {1} 标价 {2}(×{3}):{4}"
|
||||
black.sale.Listed,上架中
|
||||
black.sale.Paid,已到账
|
||||
black.sale.Lost,平台跑路,没了
|
||||
black.sale.Delisted,已撤下
|
||||
black.sale.Delisted.fake,买家看穿假卡退货
|
||||
black.kind.gpunew,显卡 全新
|
||||
merchant.GpuNew,全新矿卡
|
||||
merchant.GpuUsed,二手矿卡
|
||||
merchant.Arms,军火
|
||||
merchant.Docs,证件芯片
|
||||
merchant.Pharma,药物
|
||||
merchant.Bulk,大宗
|
||||
black.days,"{0} 天到货"
|
||||
black.sell.listedall,"已上架 {0} 件。"
|
||||
merchant.Rigs,矿架与能源
|
||||
merchant.Modules,模组
|
||||
merchant.GunMods,枪匠配件
|
||||
merchant.Chem,化学品
|
||||
merchant.Brewer,酿酒
|
||||
merchant.Farm,水培农场
|
||||
merchant.Husbandry,养殖
|
||||
merchant.Miner,矿工
|
||||
merchant.Water,水务
|
||||
merchant.Storage,仓储
|
||||
merchant.Tools,工具
|
||||
merchant.Luxury,奢侈品
|
||||
black.kind.Goods,商品
|
||||
merchant.Elite,尖端店铺
|
||||
merchant.Personal,个人卖家
|
||||
black.pay.confirm,账单
|
||||
black.pay.to,"收款地址:{0}"
|
||||
black.pay.cancel,作废
|
||||
pay.mix,"混币器 {0} {1}"
|
||||
pay.swap,"Ponero 兑换处 {0} {1}"
|
||||
black.edit.cancel,取消
|
||||
merchant.Platform,平台
|
||||
black.platform.line,平台现货 立即到货
|
||||
black.orders.in,买入
|
||||
black.orders.out,卖出
|
||||
black.desk.pair,"PONERO [隐私币] 价格 {0}"
|
||||
black.pay.amount,"金额:{0} {1}(约 {2} 信用点)"
|
||||
black.pay.wallet,打开钱包转账
|
||||
hw.total,"合计 ≈ {0} 信用点"
|
||||
hw.pending.bill,"待付:{0}"
|
||||
hw.pending.sign,"待签名:{0}"
|
||||
hw.send,发送
|
||||
hw.review,签名请求
|
||||
hw.to,收款地址
|
||||
hw.avail,"可用 {1} {0}"
|
||||
hw.amount,金额
|
||||
hw.bill,"账单:{0} {1} {2}"
|
||||
hw.fill,填入账单金额
|
||||
hw.next,✓ 下一步 × 返回
|
||||
hw.err.format,地址格式错误。
|
||||
hw.err.checksum,地址校验失败。
|
||||
hw.err.self,不可向当前钱包地址转账。
|
||||
hw.err.asset,账单指定代币为 {0}。
|
||||
hw.err.short,转账金额低于账单要求:{0} {1}。
|
||||
hw.err.nobill,无待支付账单。
|
||||
hw.review.h,核对
|
||||
hw.contract,合约调用
|
||||
hw.review.to,收款地址
|
||||
hw.review.amount,"{0} {1}(约 {2} 信用点)"
|
||||
hw.review.bill,"账单:{0}"
|
||||
hw.review.unknown,目标地址无历史交易记录。
|
||||
hw.review.over,超额支付 {0} {1},超出部分不予退还。
|
||||
hw.hold,按住 ✓ 签名 × 拒绝
|
||||
hw.tx.h,交易
|
||||
hw.tx.signing,签名中…
|
||||
hw.tx.mempool,已广播,内存池等待打包…
|
||||
hw.tx.packed,"已打包,区块 #{0}"
|
||||
hw.tx.confirm,"区块 #{0} 确认 {1}/{2}"
|
||||
hw.skip,跳过
|
||||
hw.done.h,已确认
|
||||
hw.done.block,"区块 #{0}"
|
||||
hw.done.sent,"{0} {1} → {2}"
|
||||
hw.done.void,目标地址为非活跃地址,转入资金无法找回。
|
||||
hw.back,返回
|
||||
hw.rejected,已在钱包上拒绝签名。
|
||||
hw.wait,等待钱包确认。
|
||||
hw.swap,"兑换 {0} {1} → 约 {2} {3}"
|
||||
tab.wallets,钱包
|
||||
hw.wallet.n,"钱包 {0}"
|
||||
hw.review.own,"自己的钱包:{0}"
|
||||
hw.review.poinbase,Poinbase 充值地址
|
||||
poin.deposit,"充值地址:{0}"
|
||||
wallets.count,"钱包 {0}/{1}"
|
||||
wallets.col.name,名称
|
||||
wallets.col.addr,地址
|
||||
wallets.col.taint,污点
|
||||
wallets.open,打开
|
||||
wallets.use,连接
|
||||
wallets.current,已连接
|
||||
wallets.added,"已添加{0}:{1}"
|
||||
nightlog.drained,{0}:代币已被未经授权转出,折合约 {1} 信用点。
|
||||
item.hwwallet.name,PLEDGER 硬件钱包
|
||||
item.hwwallet.desc,大屏硬件钱包。拖到交易终端上,添加一个钱包(最多 5 个)。
|
||||
poin.empty,账户为空。
|
||||
hw.copy,复制
|
||||
hw.paste,粘贴
|
||||
hw.copied,地址已复制。
|
||||
hw.copied.addr,"已复制 {0}"
|
||||
hw.balance.frozen,"(冻结 {0})"
|
||||
wallets.destroy,销毁
|
||||
wallets.destroy.sure,确认销毁
|
||||
wallets.destroyed,"已销毁{0}:{1}"
|
||||
wallets.destroy.warn,销毁 {0} 后里面的币永久丢失。再点一次确认。
|
||||
payout.label,收款
|
||||
payout.unset,未设置
|
||||
payout.set,设置地址
|
||||
payout.h,收款地址
|
||||
payout.cur,当前:{0}
|
||||
payout.pick,自己的钱包:
|
||||
payout.manual,或输入地址:
|
||||
payout.clear,清除
|
||||
payout.err,地址无效。
|
||||
nightlog.mined.lost,挖出的 {0} PSC 丢失:矿机没有设置收款地址,或地址对应的钱包已销毁。
|
||||
wallets.none,没有已加载的钱包。把硬件钱包拖到交易终端上。
|
||||
web3.err.noconn,没有连接钱包。
|
||||
web3.connect,连接钱包
|
||||
web3.disconnect,断开连接
|
||||
web3.conn,{0} {1}
|
||||
hw.balance.value,"≈ {0}"
|
||||
wallets.rename,改名
|
||||
wallets.rename.h,"{0} 新名字"
|
||||
wallets.rename.ok,确定
|
||||
hw.fee.slow,慢
|
||||
hw.fee.normal,普通
|
||||
hw.fee.fast,快
|
||||
hw.fee,"Gas 费 {0} {1}(约 {2} 信用点)"
|
||||
hw.confs,"需要 {0} 次确认"
|
||||
hw.congested,网络拥堵
|
||||
hw.congested.slow,网络拥堵:慢档可能被挤出内存池
|
||||
hw.recent,最近
|
||||
hw.recent.out,"→ {0} {1} {2}"
|
||||
hw.recent.in,"← {0} {1} {2}"
|
||||
hw.review.history,有往来记录
|
||||
hw.tx.stuck,内存池排队中…
|
||||
hw.tx.dropped,交易已被挤出内存池,未能达成,网络 Gas 费已扣除。
|
||||
hw.dropped.h,未成交
|
||||
hw.err.fee,余额不足以支付 Gas 费。
|
||||
news.congest.title,链上拥堵
|
||||
news.congest.desc,一批空投抢跑让链上排起长队,Gas 费翻了几倍,低 Gas 费的交易可能被挤出内存池。
|
||||
news.phish.title,Poinbase 公告:充值地址迁移
|
||||
news.phish.desc,"Poinbase 完成钱包系统升级,旧充值地址即将停用,请将资产转入新地址 {0}。"
|
||||
black.forum.phish,"有人贴了混币器的新地址:{0},说旧的被盯上了。"
|
||||
hw.gas,"Gas ×{0}"
|
||||
web3.sub.stake,质押
|
||||
stake.h,革命军质押池
|
||||
stake.rate,"日息 {0}%,取出要等 {1} 天,等待期间没有利息"
|
||||
stake.low,储备覆盖率告急,日息已下调
|
||||
stake.cra,"CRA 价格 {0} {1}"
|
||||
stake.none,暂无质押。
|
||||
stake.col.wallet,钱包
|
||||
stake.col.amount,质押
|
||||
stake.col.queue,等待取出
|
||||
stake.day,(第 {0} 天)
|
||||
spark.price,"平衡代币 SPARK {0} 信用点"
|
||||
stake.ops,"{0}"
|
||||
stake.avail,"CRA {0} 已质押 {1}"
|
||||
stake.do,质押
|
||||
stake.undo,申请取出
|
||||
stake.sum.in,"质押 {0} CRA"
|
||||
stake.sum.out,"申请取出 {0} CRA({1} 天后到账)"
|
||||
stake.done.in,"已质押 {0} CRA。"
|
||||
stake.done.out,"已申请取出 {0} CRA,第 {1} 天回到钱包。"
|
||||
nightlog.stakeint,"质押利息 +{0} CRA。"
|
||||
nightlog.unstaked,"质押取出的 {0} CRA 回到了{1}。"
|
||||
news.crawarn.title,革命军质押池传出异动
|
||||
news.cralow.title,革命军下调质押日息
|
||||
stake.avail2,"SPARK {0}"
|
||||
poin.sub.spot,现货
|
||||
poin.sub.perp,永续
|
||||
perp.h,永续合约
|
||||
perp.acct,"保证金账户 CRC {0}"
|
||||
perp.debt,"欠款 {0},{1} 天后没收物品抵债。没还清前不能开仓、不能出金。"
|
||||
perp.banned,永续账户已封禁,剩余 {0} 天。
|
||||
perp.none,暂无持仓。
|
||||
perp.col.pos,仓位
|
||||
perp.col.notional,名义价值
|
||||
perp.col.price,开仓 → 现价
|
||||
perp.col.pnl,盈亏
|
||||
perp.col.liq,强平价
|
||||
perp.long,多
|
||||
perp.short,空
|
||||
perp.rate,"{0} 现价 {1} 资金费 {2}%/晚"
|
||||
perp.fund,"保险基金 {0}"
|
||||
perp.open,开仓
|
||||
perp.margin,保证金金额(CRC)
|
||||
perp.do.open,开仓
|
||||
perp.do.add,追加保证金
|
||||
perp.do.close,平仓
|
||||
perp.opened,"已开 {0} {1}:保证金 {2} CRC,{3}×。"
|
||||
perp.added,"已追加 {0} CRC 保证金。"
|
||||
perp.closed,"已平仓,{0} CRC 回到账户(盈亏 {1})。"
|
||||
perp.deficit,账户权益不足,缺口 {0} 由保险基金及欠款承担。
|
||||
perp.err.Banned,永续账户已被封禁。
|
||||
perp.err.Debt,存在未清欠款,禁止开仓。
|
||||
perp.err.Leverage,杠杆倍数超出该标的上限。
|
||||
perp.err.Size,超出该标的单仓名义价值上限。
|
||||
perp.err.Funds,账户 CRC 余额不足(含手续费)。
|
||||
perp.err.Opposite,同一标的不可双向持仓,须先平仓现有持仓。
|
||||
perp.err.NoPosition,当前无持仓。
|
||||
perp.err.Margin,未输入保证金数量。
|
||||
perp.debt.block,存在永续欠款,限制出金。
|
||||
nightlog.perp.liq,{0} 触发强制平仓,扣除保证金 {1}。
|
||||
nightlog.perp.adl,保险基金耗尽,{0} 盈利仓位触发自动减仓,扣减盈利 {1}。
|
||||
nightlog.perp.interest,永续欠款计息,当前欠款总额 {0}。
|
||||
nightlog.perp.seize,永续欠款逾期,罚没物品抵扣欠款 {0}。
|
||||
nightlog.perp.writeoff,未偿缺口 {0} 已核销,永续账户封禁 {1} 天。
|
||||
perp.slip.title,永续欠款没收单
|
||||
perp.preview2,"手续费 {0} 强平价 {1}"
|
||||
nightlog.perp.repaid,"永续穿仓欠款,从 Poinbase 账户扣了 {0} CRC 还款。"
|
||||
perp.err.Thin,订单预期滑点过大将立即触发强平。需降低开仓金额或杠杆倍数。
|
||||
perp.err.Single,同一时间只能持有一个仓位,只能追加保证金。
|
||||
mat.hypertech_electronic,超科技电子元件
|
||||
item.asic.name,RatDigg {0} 矿机
|
||||
item.asic.dead.name,损坏的 RatDigg {0} 矿机
|
||||
item.asic.desc,标称算力 {0} GH/s。标称耗电 {1} kJ/天。成色 {2}。独立矿机:放电池才挖,可以放模块。
|
||||
item.asic.dead.desc,烧坏了。把电子元件拖到它身上修好:现在要 {0} × {1}。修好后健康 −20。
|
||||
item.asic.dead.fixed,已经修好。
|
||||
merchant.Asic,矿机商
|
||||
black.kind.asic,矿机 成色 {0}%
|
||||
black.kind.asicnew,矿机 全新
|
||||
news.erawarn.title,RatDigg 新一代矿机即将发布
|
||||
news.erawarn.desc,专用矿机厂商宣布新品,业内预计不久后大型矿场会成批换机。有人说显卡挖矿的好日子要到头了。
|
||||
news.era.title,矿机时代
|
||||
news.era.desc,新一代专用矿机开始量产,大型矿场的耗电成本砍掉一半。全网算力会涨上去,显卡矿工的收益要被摊薄。
|
||||
web3.sub.predict,预测
|
||||
predict.h,预测市场
|
||||
predict.acct,链上钱包 {0}:CRC {1}
|
||||
predict.none,今日无开放盘口。
|
||||
predict.closed,已封盘
|
||||
predict.row,是 {0} 否 {1}
|
||||
predict.held,持有「{0}」{1} 份,成本 {2}
|
||||
predict.yes,是
|
||||
predict.no,否
|
||||
predict.void,作废
|
||||
predict.result,第 {0} 天 {1} 结果:{2} {3}
|
||||
predict.pick,买卖
|
||||
predict.price,每份现价:是 {0} 否 {1}
|
||||
predict.pos,{0}:押「{1}」{2} 份
|
||||
predict.pos2,成本 {0} 押中得 {1}
|
||||
predict.sum.buy,"买入「{1}」,花 {2} CRC:{0}"
|
||||
predict.sum.sell,卖出预测持仓:{0}
|
||||
predict.closed.note,已封盘,等待结算。
|
||||
predict.preview,买「{0}」约 {1} 份(均价 {2}),押中净赚 {3}
|
||||
predict.buy.yes,买入「是」
|
||||
predict.buy.no,买入「否」
|
||||
predict.sell,全部卖出
|
||||
predict.bought,买入「{0}」,花 {2},押中可得 {1}。
|
||||
predict.sold,卖出,收回 {0}。
|
||||
predict.err.Closed,这个盘口已经封盘。
|
||||
predict.err.Amount,金额不对。
|
||||
predict.err.Funds,钱包里的 CRC 不够。
|
||||
predict.err.Cap,超过这个盘口的持仓上限。
|
||||
predict.err.Opposite,这个盘口已经持有另一边,先全部卖出。
|
||||
predict.err.NoPosition,这个盘口没有持仓。
|
||||
predict.win.one,第 {0} 天
|
||||
predict.win.range,第 {0}–{1} 天
|
||||
predict.q.event,{0}:出现「{1}」
|
||||
predict.q.faction,{0}:{1}有行动开始
|
||||
predict.q.purity,{0}:{1}纯度 ≥ {2}
|
||||
predict.q.price,{0}:{1} 价格 ≥ {2}
|
||||
predict.faction.FACTION_SECURITY,安保派
|
||||
predict.faction.FACTION_REVOLUTION,革命军
|
||||
predict.faction.FACTION_LOWER_LEVEL,下层
|
||||
predict.faction.FACTION_UPPER_LEVEL,上层
|
||||
predict.faction.FACTION_BLACK_MARKET,黑市
|
||||
predict.purity.gutter,下层水
|
||||
predict.purity.rust,上层水
|
||||
nightlog.predict.win,预测押中:「{0}」,兑付 {1}。
|
||||
nightlog.predict.lose,预测押错:「{0}」,本金 {1} 没了。
|
||||
nightlog.predict.void,预测作废:「{0}」,退回本金 {1}。
|
||||
nightlog.predict.caught,内幕下注被查:「{0}」,本金和收益 {1} 全部没收,记诈骗罪证。
|
||||
predict.tab.markets,盘口
|
||||
predict.tab.intel,情报
|
||||
predict.acct.crt,链上钱包 {0}:CRT {1}
|
||||
predict.tier.0,低档
|
||||
predict.tier.1,中档
|
||||
predict.tier.2,高档
|
||||
predict.clue.tip,情报({0}):「{1}」
|
||||
predict.clue.queued,排期:第 {0} 天开始
|
||||
predict.clue.queued2,排期:第 {0} 天「{1}」
|
||||
predict.clue.cool,该事件进行中或冷却中
|
||||
predict.clue.busy,该派系行动进行中,近期无新行动
|
||||
predict.clue.halving,减半在第 {0} 天,前一周抬价
|
||||
predict.clue.anchor,当前价格锚 {0}
|
||||
predict.clue.gas,近几天 gas:{0}
|
||||
predict.clue.drain,每晚消耗 {0}
|
||||
predict.clue.era,第 {0}–{1} 天间随机,提前预告
|
||||
predict.clue.era.warned,预告已出:第 {0}–{1} 天开始
|
||||
predict.q.gas,{0}:gas 指数 ≥ {1}
|
||||
predict.q.cra,{0}:CRA 发出预警
|
||||
predict.q.era,{0}:矿机时代开始
|
||||
predict.era,矿机时代
|
||||
predict.pos3,均价 {0} 现价 {1}
|
||||
predict.pos4,当前卖出可得 {0}
|
||||
intel.h,情报贩子
|
||||
intel.locked,需要 Web3 商店和黑市声望 {0}。
|
||||
intel.brief.buy,购买局势简报({0} CRT)
|
||||
intel.brief.none,尚未购买简报。
|
||||
intel.brief.day,第 {0} 天的简报
|
||||
intel.tips.h,内幕消息
|
||||
intel.tips.none,无可查询的盘口(仅限派系行动与矿机时代)。
|
||||
intel.tip.buy,准确率约 {0}% {1} CRT
|
||||
intel.err.funds,钱包 CRT 不足,或该盘口已不可交易。
|
||||
intel.brief.sum,局势简报,{0} CRT
|
||||
intel.tip.sum,内幕消息 {0} CRT:{1}
|
||||
intel.brief.done,已取得局势简报。
|
||||
intel.tip.done,情报内容:「{0}」。
|
||||
predict.brief.levels,安保 {0} 革命军 {1} 黑市 {2} 动荡 {3} 上层 {4}
|
||||
predict.brief.busy,{0}:行动进行中
|
||||
predict.brief.queued,{0}:行动已排期
|
||||
predict.brief.none,{0}:暂时发起不了
|
||||
predict.brief.can,{0}:可发起 {1}
|
||||
predict.clue.push,玩家推价 {0}%,操纵风险高
|
||||
nightlog.predict.manip,预测被判操纵:「{0}」,本金 {1} 没收,记诈骗罪证。
|
||||
news.manip.title,交易所调查异常交易
|
||||
news.manip.desc,监管部门通报,有人用大额现货单推动价格,从合约和预测里获利,涉事资金已被追缴。
|
||||
perp.manip,平仓盈利 {0} 被判操纵价格,已没收,永续账户冻结 {1} 天。
|
||||
web3.sub.ponzi,理财
|
||||
ponzi.h,高息理财
|
||||
ponzi.acct,发行钱包 {0}:CRC {1}
|
||||
ponzi.rate,日息 {0}%
|
||||
ponzi.pool,池子 {0} / 上限 {1}
|
||||
ponzi.inflow,昨日存入 {0}
|
||||
ponzi.interest,今晚应付利息 {0}
|
||||
ponzi.own,自付利息合计 {0}
|
||||
ponzi.wind,举报风险:{0}
|
||||
ponzi.wind.low,低
|
||||
ponzi.wind.mid,中
|
||||
ponzi.wind.high,高
|
||||
ponzi.idle,未发行理财产品。
|
||||
ponzi.done,理财产品已关闭。每个存档限发行一次。
|
||||
ponzi.ops,操作
|
||||
ponzi.rug,卷走资金池({0})
|
||||
ponzi.rug.confirm,确认卷走 {0}
|
||||
ponzi.rugged,已卷走 {0},污点全额。
|
||||
ponzi.open,发行理财产品
|
||||
ponzi.ad,宣传费 {0} CRC,从当前钱包支付,需签名。
|
||||
ponzi.start,发行
|
||||
ponzi.started,理财产品已发行。
|
||||
ponzi.err,钱包 CRC 不足以支付宣传费。
|
||||
nightlog.ponzi.collapse,理财付不出利息,挤兑,池子 {0} 被没收,记诈骗罪证,下层声望清零。
|
||||
nightlog.ponzi.reported,理财被举报,池子 {0} 被没收,记诈骗罪证,下层声望清零。
|
||||
news.ponzi.title,高息理财爆雷
|
||||
news.ponzi.desc,下层有人发行的高息理财被举报,投资人围堵,资金已被监管冻结。
|
||||
news.ponzi.rug.title,理财骗局
|
||||
news.ponzi.rug.desc,一款高息理财的发行人卷走了全部资金,下层的投资人血本无归。
|
||||
ponzi.start.sum,开高息理财,日息 {0}%,宣传费 {1} CRC
|
||||
ponzi.rug.sum,卷走理财池 {0}
|
||||
ponzi.err.wallet,需用发行钱包签名。
|
||||
predict.clue.counter,情报:已排期(柜台线人、传闻纸条)
|
||||
web3.sub.airdrop,空投
|
||||
air.h,空投
|
||||
air.none,暂无可领取的空投。
|
||||
air.row,{0} 奖励 {1} CRC {2} 第 {3} 天截止
|
||||
air.claim,领取
|
||||
air.unlimited,授权 {0} 无上限
|
||||
air.limited,授权 {0} {1}
|
||||
air.approvals,{0} 的授权
|
||||
air.approvals.none,没有授权。
|
||||
air.approval,{0}:{1}
|
||||
air.revoke,撤销
|
||||
air.sum,领取空投 {0}({1})
|
||||
air.claimed,已领取 {0} CRC。
|
||||
air.auth,授权钱包
|
||||
air.unauth,未授权
|
||||
air.authed,已授权:{0}
|
||||
air.authed.msg,已为 {0} 授权钱包。
|
||||
air.auth.sum,授权 {0} 代表本钱包操作。范围:{1}。
|
||||
air.err.unauth,先为这个空投授权钱包。
|
||||
air.revoke.sum,撤销 {0} 的 {1} 授权
|
||||
air.revoked,授权已撤销。
|
||||
air.err.wallet,需用授权钱包签名。
|
||||
pool.h,第三方收益池(CRC)
|
||||
pool.none,暂无收益池。
|
||||
pool.col.name,池子
|
||||
pool.col.rate,日息
|
||||
pool.col.reserve,储备
|
||||
pool.col.lock,时间锁
|
||||
pool.col.audit,审计
|
||||
pool.col.mine,存款
|
||||
pool.yes,有
|
||||
pool.no,无
|
||||
pool.pending,取款中
|
||||
pool.closed,(已关闭)
|
||||
pool.deposit,存入
|
||||
pool.withdraw,取出
|
||||
pool.withdraw.lock,申请取出({0} 天)
|
||||
pool.err.cap,超过资金池上限,可存额度 {0}。
|
||||
pool.err.none,没有存款。
|
||||
pool.sum.in,存入 {0}:{1} CRC
|
||||
pool.sum.out,从 {0} 取出 {1} CRC
|
||||
pool.done.in,存入 {0} CRC 到 {1}。
|
||||
pool.done.out,取出 {0} CRC。
|
||||
pool.done.lock,已申请取出 {0} CRC,第 {1} 天到账。
|
||||
nightlog.scam.drain,{0} 的 {1} {2} 被「{3}」用授权转走了。
|
||||
nightlog.scam.rug,收益池「{0}」跑路,{2} 存的 {1} CRC 没了。
|
||||
nightlog.scam.dry,收益池「{0}」储备用完关闭,{2} 的 {1} CRC 退回。
|
||||
nightlog.scam.paid,收益池「{0}」取款到账:{2} 收到 {1} CRC。
|
||||
nightlog.scam.fakepay,伪造转账:{0}
|
||||
nightlog.scam.sent,转给「客服」安全地址的 {0} {1} 进了骗子的口袋。
|
||||
coinpay.intro,我用 {0} 付,链上确认要一会儿。
|
||||
coinpay.intro.fake,{0} 我已经转过去了,截图给你看,赶紧给货,我赶时间。
|
||||
coinpay.fake.entry,{0} 拿走了 {1},说付了 {2} 信用点的币,链上没有这笔。
|
||||
scam.support.name,Poinbase 客服
|
||||
scam.support.1,您好,我是 Poinbase 客服。系统检测到您的账户有异常登录,已经被风控了。
|
||||
scam.support.2,请在今天内把 {0} CRC 转到安全地址 {1} 做验证,验证完马上退回。
|
||||
scam.support.3,不处理的话账户会被永久冻结。我先走了,记得转。
|
||||
predict.sold.caught,卖出时内幕交易被查:本金和收益全部没收,记诈骗罪证。
|
||||
predict.row.move,(昨晚 {0} {1})
|
||||
predict.stats.h,历史(开盘均价 / 实际发生)
|
||||
predict.stats.row,{0}:{1} 个,开盘均价 {2},发生 {3}%
|
||||
predict.kind.Event,新闻事件
|
||||
predict.kind.Faction,派系行动
|
||||
predict.kind.Purity,水纯度
|
||||
predict.kind.Price,PSC 价格
|
||||
predict.kind.Gas,gas
|
||||
predict.kind.Cra,CRA 预警
|
||||
predict.kind.Era,矿机时代
|
||||
nightlog.predict.move,预测盘「{0}」价格 {1} → {2}
|
||||
nightlog.predict.why,({0})
|
||||
chart.empty,{0} 日K:暂无历史,自今日起记录。
|
||||
chart.caption,{0} 日K 高 {2} 低 {3} 收 {4}({5}%)
|
||||
chart.legend,<size=80%>绿涨红跌 黄线 7 日均线 柱:灰 市场 / 青 玩家</size>
|
||||
chart.legend.thr,<size=80%>绿涨红跌 黄线 7 日均线 蓝虚线 阈值</size>
|
||||
news.story.serpico_rev.title,革命军握有治安部把柄
|
||||
news.story.serpico_rev.desc,据传革命军拿到了治安部内部腐败的证据。质押池传出消息:一笔大额资金注入革命军储备,SPARK 近日走强。
|
||||
news.story.serpico_bm.title,黑市与治安部达成默契
|
||||
news.story.serpico_bm.desc,一份治安部内部文件在黑市易手。此后暗网结算通道明显稳定,CRT 的兑付没再出过岔子。
|
||||
news.story.serpico_sec.title,治安部启动内部整顿
|
||||
news.story.serpico_sec.desc,治安部宣布彻查内部腐败,同时加强对资金流向的监控。Poinbase 收紧出金审查,混币服务被点名。
|
||||
news.story.eleanor_leak.title,营养果育种数据曝光
|
||||
news.story.eleanor_leak.desc,下层报社公开了一份营养果重新结籽的研究数据,帕斯泰尔公司股价重挫。托管上层资金的银行传出坏账,革命军声势上涨。
|
||||
news.story.eleanor_return.title,帕斯泰尔追回失窃数据
|
||||
news.story.eleanor_return.desc,帕斯泰尔公司证实追回一份失窃的研究数据。上层资本松了口气,CRC 的托管银行评级上调。
|
||||
news.story.lun_arrested.title,伦警官因滥用职权被捕
|
||||
news.story.lun_arrested.desc,治安部当场逮捕了滥用职权的伦警官,并表示接下来两周将从严查处各类违法交易。
|
||||
tumbler.name,Tumbler
|
||||
tumbler.v1.1,你好。听说你这儿的终端连着我的混币器。
|
||||
tumbler.v1.2,那东西是我写的。圈子里都叫我 Tumbler。
|
||||
tumbler.v1.3,它不碰你的货,也不记你的账,只是把币搅匀。
|
||||
tumbler.v1.4,顺路过来看看,用户长什么样。
|
||||
tumbler.v2.1,最近不太平。治安部在查链上的混币服务。
|
||||
tumbler.v2.2,他们盯上了几个大额地址,顺着摸到了我的节点。
|
||||
tumbler.v2.3,这几天混币器要是停了,别慌,在里面的币不会丢。
|
||||
tumbler.v3.1,节点被封了。他们迟早会查到我住的地方。
|
||||
tumbler.v3.2,我手上有个密钥盘,里面是混币器的签名密钥。
|
||||
tumbler.v3.3,要是落到治安部手里,所有用户的记录都能还原出来。包括你的。
|
||||
tumbler.v3.ask,能帮我藏几天吗?
|
||||
tumbler.v3.choice.hide,[收下密钥盘,帮他藏好]
|
||||
tumbler.v3.choice.report,[假装答应,转头通知治安部]
|
||||
tumbler.v3.choice.sell,[收下密钥盘,转手卖给黑市]
|
||||
tumbler.v3.thanks1,谢了。过几天我来取。
|
||||
tumbler.v3.thanks2,别放在显眼的地方。搜查的时候被翻出来,咱俩都完蛋。
|
||||
tumbler.v3.report1,……好。我晚点再过来。
|
||||
tumbler.v4.back.1,我来取密钥盘了。
|
||||
tumbler.v4.back.2,节点挪到了新地方,治安部一时半会儿找不着。
|
||||
tumbler.v4.back.3,这是谢礼。以后你用混币器,手续费给你打对折。
|
||||
tumbler.v4.lost.1,密钥盘呢?
|
||||
tumbler.v4.lost.2,……你把它弄丢了?
|
||||
tumbler.v4.lost.3,算了。我自己想办法。
|
||||
tumbler.v4.sold.1,密钥盘是你卖给黑市的吧。
|
||||
tumbler.v4.sold.2,混币器现在归他们管了。费用翻了一倍,用户的钱随时可能被卷走。
|
||||
tumbler.v4.sold.3,我会记住这件事的。
|
||||
tumbler.v4.none.1,算了,当我没来过。
|
||||
item.keydrive.name,密钥盘
|
||||
item.keydrive.desc,Tumbler 托你保管的数据棒,里面是混币器的签名密钥。违禁品,搜查时被翻出来会记罪证。
|
||||
mixer.closed,混币器已关停,不再接受存入。在途资金照常提回。
|
||||
news.tumbler.sanction.title,治安部查封混币节点
|
||||
news.tumbler.sanction.desc,治安部宣布查封一处链上混币服务的节点,称其为洗钱提供便利。服务暂时中断。
|
||||
news.tumbler.caught.title,混币器运营者落网
|
||||
news.tumbler.caught.desc,化名 Tumbler 的混币器运营者在下层区被捕。治安部表示,相关混币服务已永久关停。
|
||||
news.tumbler.sold.title,混币服务易主
|
||||
news.tumbler.sold.desc,有消息称,下层区一家混币服务的签名密钥已落入黑市之手,费用随即上调。用户担心资金安全。
|
||||
nightlog.tumbler.gift,Tumbler 取回了密钥盘,留下 {0} CRT 谢礼(已转入 {1}),混币器手续费减半。
|
||||
mixer.status.closed,状态:已关停
|
||||
yield.sub.pools,收益池
|
||||
yield.sub.mine,发行理财
|
||||
pool.side.h,存入
|
||||
ponzi.early,第 {0} 天起可发行高息理财。
|
||||
bpay.h,付款
|
||||
bpay.qty,数量
|
||||
bpay.total,合计 {0} 信用点等值
|
||||
bpay.need,"需付 {0} {1} 钱包余额 {2}"
|
||||
bpay.invoice,生成账单
|
||||
bpay.swap.h,"自动换币为 {0}"
|
||||
bpay.swap.none,钱包里没有足够的其他币种
|
||||
bpay.swap.need,"付 {0} {1},含滑点 {2}%"
|
||||
bpay.swap.btn,自动换币并付款
|
||||
bpay.swap.sum,"{0}:自动换币,付 {2} {1},换成 {3} 后下单"
|
||||
bpay.back,返回
|
||||
cart.fab,购物车 {0}
|
||||
cart.h,购物车
|
||||
cart.empty,购物车是空的。
|
||||
cart.added,已加入购物车:{0}
|
||||
cart.back,返回商店
|
||||
cart.done,"已结算 {0} 件。"
|
||||
cart.partial,"已结算 {0} 件,{1} 件没成(库存或余额不足)。"
|
||||
black.info.accepts,收币:{0}
|
||||
black.info.advance.yes,接受提前放款
|
||||
black.info.advance.no,不接受提前放款
|
||||
settings.section.ui,界面
|
||||
settings.section.story,剧情
|
||||
settings.section.difficulty,难度
|
||||
settings.terminal_size,交易终端窗口大小
|
||||
settings.terminal_size_desc,窗口尺寸(宽×高,界面单位)。下次打开终端时生效。
|
||||
settings.tumbler_story,Tumbler 剧情
|
||||
settings.tumbler_story_desc,Tumbler 上门与藏密钥盘的支线。关闭后不再有新的上门,已有进度保留。
|
||||
settings.risk_scale,风险倍率
|
||||
settings.risk_scale_desc,骗局、跑路、钱包投毒、地址劫持和钓鱼的发生概率倍数。对所有存档生效。
|
||||
settings.mining_scale,挖矿产出倍率
|
||||
settings.mining_scale_desc,挖矿设备拿到的区块奖励倍数。对所有存档生效。
|
||||
gg.header,空间站贸易委员会
|
||||
gg.p1.cap,显卡图示
|
||||
gg.p1.makers,空间站上共有两家常见的制造商:\n\n - Probidia(“PB”)\n - PMD(“MD”)
|
||||
gg.p1.note,无论制造商是谁,显卡的价值只取决于真实芯片的型号定价和健康度:满健康时等于型号定价,健康度为 0 时只剩 {CardValueFloor:%}。
|
||||
gg.fan.h,叶片
|
||||
gg.fan.0,叶片干净(价格不变)
|
||||
gg.fan.1,叶片积灰(-{CardFanDust:%})
|
||||
gg.fan.2,叶片缺角(-{CardFanChipped:%})
|
||||
gg.fin.h,金手指
|
||||
gg.fin.0,光亮(价格不变)
|
||||
gg.fin.1,发暗(-{CardFingersDark:%})
|
||||
gg.fin.2,氧化发绿(-{CardFingersOxidized:%})
|
||||
gg.brk.h,挡板
|
||||
gg.brk.0,挡板完好(价格不变)
|
||||
gg.brk.1,挡板划痕(-{CardBracketScratch:%})
|
||||
gg.seal.h,封条
|
||||
gg.seal.0,封条完好(价格不变)
|
||||
gg.seal.2,封条缺失(-{CardSealMissing:%})
|
||||
gg.wear.note,叶片、金手指、挡板随每晚损耗变差,只会越来越旧;封条是固定特征。成色还会影响算力、损耗和暴毙概率。
|
||||
gg.serial.h,序列号
|
||||
gg.serial.cap,背面图示(序列号贴纸)
|
||||
gg.serial.pb,Probidia(“PB”)\n 合规工厂码:11、12、21、34、47
|
||||
gg.serial.md,PMD(“MD”)\n 合规工厂码:13、22、35、41、58
|
||||
gg.print.h,背面丝印
|
||||
gg.print.0,与型号一致
|
||||
gg.print.1,印着另一个型号(假冒)
|
||||
gg.print.2,重印过,字歪(假冒)
|
||||
gg.point.h,指出
|
||||
gg.ex.card,示例:{0},健康度 {1}%
|
||||
gg.ex.base,基础价值:+{0}
|
||||
gg.ex.fan,叶片缺角:-{0}
|
||||
gg.ex.fin,金手指发暗:-{0}
|
||||
gg.ex.seal,封条缺失:-{0}
|
||||
gg.ex.total,最终价值:{0}
|
||||
gg.ex.note,各项折价都按基础价值计算,相加后扣除。
|
||||
gg.ex.fan1,叶片积灰:-{0}
|
||||
gg.ex.fin2,金手指氧化:-{0}
|
||||
gg.ex.brk,挡板划痕:-{0}
|
||||
gg.ex.nodisc,没有折价:-0
|
||||
gg.ex.fake,标称 {0},实际芯片 {1}:按实际芯片计价
|
||||
gg.ex.claimed,按标称型号的报价:{0}
|
||||
gg.ex.gap,与报价相差:{0}
|
||||
gg.ex.h2,鉴定示例:假冒显卡
|
||||
gg.ex.h3,鉴定示例:成色很差的显卡
|
||||
gg.ex.h4,鉴定示例:轻微使用
|
||||
gg.ex.h5,鉴定示例:全新显卡
|
||||
lbl.price,标签价:{0}
|
||||
lbl.row.count,风扇数
|
||||
lbl.row.pin,供电口
|
||||
lbl.count.1,单风扇
|
||||
lbl.count.2,双风扇
|
||||
lbl.count.3,三风扇
|
||||
lbl.pin.0,6 针
|
||||
lbl.pin.1,8 针
|
||||
lbl.pin.2,双 8 针
|
||||
gg.p1.body,显卡是矿机的核心部件,也是二手市场上最常被假冒的货物。\n判断一张显卡是不是正品,看四项:风扇数、供电口、背面丝印、序列号。四项全部符合标称型号才是正品,任何一项对不上就是假冒。\n显卡的价值取决于真实芯片的型号和健康度,外观上的每一处磨损都会折价。\n\n本指南将提供鉴定显卡所需的全部知识。
|
||||
gg.p2.h,显卡型号
|
||||
gg.p2.body,型号决定风扇数和供电口。假冒显卡是低型号的芯片套着高型号的外壳,性能和价值都按里面的真实芯片算。
|
||||
gg.tier.0,RTX 60 / RX 70:6 针,单风扇
|
||||
gg.tier.1,RTX 70 / RX 80:8 针,双风扇
|
||||
gg.tier.2,RTX 80 / RX 800:8 针,三风扇
|
||||
gg.tier.3,RTX 90 / RX 900:双 8 针,三风扇
|
||||
gg.count.h,风扇数
|
||||
gg.count.body,风扇数由型号决定:RTX 60 和 RX 70 为单风扇,RTX 70 和 RX 80 为双风扇,RTX 80、RTX 90、RX 800 和 RX 900 为三风扇。\n实物的风扇数对不上标称型号,即为假冒。
|
||||
gg.pin.h,供电口
|
||||
gg.pin.body,供电口也由型号决定:RTX 60 和 RX 70 为 6 针,RTX 70、RTX 80、RX 80 和 RX 800 为 8 针,RTX 90 和 RX 900 为双 8 针。\n实物的供电口对不上标称型号,即为假冒。
|
||||
gg.serial.body,序列号贴在显卡背面,格式为:前缀、型号码、连字符、两位工厂码、连字符、四位流水号,例如 PB2-21-6251。
|
||||
gg.serial.rule,型号码 1 至 4 依次对应 RTX 60 / RX 70、RTX 70 / RX 80、RTX 80 / RX 800、RTX 90 / RX 900。\n型号码与型号不符(贴的是原芯片的序列号),或工厂码、位数不合规(后补的贴纸),均为假冒。工厂码只用来判真伪,不影响价格。
|
||||
gg.print.note,风扇数、供电口、丝印、序列号四项全部符合才是正品。假冒显卡至少有一项对不上,但可能其余几项都做得规矩,所以每一项都要看。
|
||||
gg.point.body,用放大镜检视。标签栏里只有型号一行有“指出型号”按钮,下面的风扇数、供电口、背面丝印、序列号四行只读;叶片、金手指、挡板、封条四项成色各有自己的“指出”。\n指出隐瞒的成色问题,这一行改成真实情况,价格按差额回落;指出的是真话,对方不认,信誉受损。\n风扇数、供电口、丝印、序列号任何一项与标称型号对不上,就指出型号:这张卡被认定为假冒,型号改回真实芯片,价格按真实芯片重算。\n\n鉴定公会的客户带来的卡也一样:指出问题后估价跟着变,最后报出正确价值。
|
||||
gg.ex.serial,序列号:{0}
|
||||
gg.ex.h,鉴定示例:叶片缺角、金手指发暗、封条缺失
|
||||
rig.label.status,状态
|
||||
rig.st.cards,显卡数
|
||||
rig.st.power,耗电
|
||||
rig.st.hash,算力
|
||||
rig.st.kj,{0} kJ/天
|
||||
lbl.point.model,指出型号
|
||||
col.crcprice,CRC 价格
|
||||
swap.pay,支付
|
||||
swap.get,获得
|
||||
swap.preview,约得 {0} {1} 经 {2} 个池,损耗 {3}%
|
||||
swap.go,兑换
|
||||
swap.same,支付和获得的币种不能相同。
|
||||
mint.need,需要 {0} CRC 和 {1} SPARK
|
||||
mint.reserve,储备覆盖率 {0}% 抵押率 {1}%
|
||||
mint.queue,待处理
|
||||
mint.order,{0} {1} CRA,第 {2} 天
|
||||
stake.coin,存入币种
|
||||
stake.sum.via,兑换 {0} {1} → 约 {2} CRA 并质押
|
||||
nightlog.cra.lost,官方没有回应:{0} CRA 的{1}单丢失。
|
||||
news.crawarn.desc,有人在清点革命军的储备,质押的 CRA 恐怕兑付不了。解锁需要四天,有人说该动手了。
|
||||
news.cralow.desc,储备覆盖率告急,革命军把 CRA 质押日息降到了原来的零头。
|
||||
poin.sub.funds,资金
|
||||
funds.receive,入金
|
||||
funds.send,出金
|
||||
funds.bank,银行账户
|
||||
funds.wallet,钱包
|
||||
funds.to,收款地址
|
||||
funds.go,发送
|
||||
funds.sending,正在转出 {0} {1} 到 {2}
|
||||
funds.confirm,确认 {0}/{1}
|
||||
funds.done,{0} {1} 已到账:{2}。
|
||||
funds.done.void,已转出 {0} {1};该地址无人持有,币无法找回。
|
||||
funds.err.addr,地址格式或校验位不对。
|
||||
funds.err.self,这是 Poinbase 自己的充值地址。
|
||||
funds.err.known,该地址只接受对应账单的付款。
|
||||
funds.err.fee,数额不够付 Gas 费。
|
||||
wallets.sub.explorer,浏览器
|
||||
explorer.search,地址
|
||||
explorer.all,最近
|
||||
explorer.none,没有转账记录。
|
||||
explorer.col.block,区块
|
||||
explorer.col.amount,数额
|
||||
explorer.mixer,混币器
|
||||
cra.mint,铸造
|
||||
cra.burn,销毁
|
||||
mint.h,官方铸造(CRC 加 SPARK)
|
||||
mint.sum.in,用 {1} CRC 和 {2} SPARK 铸造 {0} CRA({3}~{4} 天)
|
||||
mint.sum.out,销毁 {0} CRA 换回 CRC 和 SPARK({1} 天)
|
||||
mint.done.in,已提交铸造,第 {0} 天结算。
|
||||
mint.done.out,已提交销毁,第 {0} 天结算。
|
||||
nightlog.cra.minted,铸造的 {0} CRA 已进入质押({1})。
|
||||
nightlog.cra.burned,销毁 {0} CRA:收回 {1} CRC、{2} SPARK({3})。
|
||||
predict.clue.subsidy,储备余量 {0}%,归零必预警
|
||||
air.noapprove,无需代币额度
|
||||
tab.gray,灰网
|
||||
wallets.sub.list,钱包列表
|
||||
entry.web3.l1,去中心化交易与质押
|
||||
entry.mining.l1,矿机状态与夜间收益
|
||||
entry.gray.l1,混币器与商店
|
||||
entry.wallets.l1,硬件钱包与浏览器
|
||||
entry.wallets.l2,钱包 {0} / {1}
|
||||
black.sell.add,上架更多
|
||||
black.sell.back,返回橱窗
|
||||
black.sell.kinds,上架 {0}/{1} 种
|
||||
black.sell.have,上架 {0} 件
|
||||
black.sell.coins,收款币种
|
||||
black.sell.off,下架
|
||||
black.sell.off.n,下架 ×{0}
|
||||
black.sell.nocoin,至少接受一种币。
|
||||
black.sell.empty,暂无上架的货。
|
||||
black.sell.delisted,已下架 {0} 件,货已回到储藏区。
|
||||
black.sell.partial,已上架 {0} 件,{1} 件未能上架。
|
||||
black.sell.limit.stack,每种商品最多上架 {0} 件。
|
||||
black.sell.limit.kinds,最多同时上架 {0} 种。
|
||||
shelf.fab,货架 {0}
|
||||
delist.fab,确定下架 {0}
|
||||
black.fee.h,准备上架
|
||||
black.fee.line,{0} ×{1} 标价 {2}({3})
|
||||
black.fee.total,上架费 {0}
|
||||
black.fee.sum,上架费({0} 件)
|
||||
black.sale.Sold,已成交,第 {0} 天以 {1} 放款
|
||||
explorer.col.day,天
|
||||
explorer.day,第 {0} 天
|
||||
explorer.pool,RatDigg 矿池
|
||||
explorer.desk,Ponero 兑换处
|
||||
black.fee.pay,支付平台费
|
||||
explorer.col.from,转出
|
||||
explorer.col.to,转入
|
||||
rig.st.cond,成色
|
||||
asic.st.dead,已烧毁
|
||||
perp.preview,名义价值 {0} 预估均价 {1}(滑点 {2}%)
|
||||
perp.sim.close,平仓 名义价值 {0} 预估均价 {1}(滑点 {2}%)
|
||||
perp.sim.close2,手续费 {0} 约回 {1} CRC(盈亏 {2})
|
||||
trade.sim.sell,卖出约得 {0} {1} 均价 {2} 滑点 {3}%
|
||||
trade.sim.buy,买入约需 {0} {1} 均价 {2} 滑点 {3}%
|
||||
trade.amount.unit,数量({0})
|
||||
trade.fee,手续费 {0}%
|
||||
trade.sim.thin,超出池子流动性
|
||||
news.wipe.down.title,{0} 单日下跌 {1}%,{2} 人爆仓
|
||||
news.wipe.down.desc,过去一天,{0} 永续合约有 {1} 个多头仓位爆仓,爆仓总额 {2} 信用点。Poinbase 保险基金余额 {3} 信用点。
|
||||
news.wipe.up.title,{0} 单日上涨 {1}%,{2} 人爆仓
|
||||
news.wipe.up.desc,过去一天,{0} 永续合约有 {1} 个空头仓位爆仓,爆仓总额 {2} 信用点。Poinbase 保险基金余额 {3} 信用点。
|
||||
hot.name,出货人
|
||||
hot.intro.CRT,最近风声紧,这批 CRT 留在手里烫手,得尽快换成现金。
|
||||
hot.intro.PSC,有家矿场的钱包昨晚换了主人。PSC 在我这儿,我只要现金。
|
||||
hot.intro.PONERO,一笔赎金,Ponero,查不到来路。我只收现金。
|
||||
hot.offer,{0} {1},按现价值 {2}。给我 {3} 现金,币当场转给你。
|
||||
hot.choice.yes,收下
|
||||
hot.choice.no,不要
|
||||
hot.say.yes,成交。
|
||||
hot.say.no,这钱我不碰。
|
||||
hot.done,币转过去了。我们没见过。
|
||||
hot.refused,有的是人要。
|
||||
hot.nocash,现金都拿不出来?那算了。
|
||||
hot.nowallet,钱包都没连上,币往哪儿转?算了。
|
||||
hot.sting,别动,治安部。收购赃款,现金没收,这笔会记进你的档案。
|
||||
hw.err.poinbase,Poinbase 不收 {0}。
|
||||
|
After Width: | Height: | Size: 495 B |
|
After Width: | Height: | Size: 502 B |
|
After Width: | Height: | Size: 500 B |
|
After Width: | Height: | Size: 1.5 KiB |
|
After Width: | Height: | Size: 2.5 KiB |
|
After Width: | Height: | Size: 349 B |
|
After Width: | Height: | Size: 397 B |
|
After Width: | Height: | Size: 380 B |
|
After Width: | Height: | Size: 340 B |
|
After Width: | Height: | Size: 462 B |
|
After Width: | Height: | Size: 509 B |
|
After Width: | Height: | Size: 569 B |
|
After Width: | Height: | Size: 1.3 KiB |
|
After Width: | Height: | Size: 1.8 KiB |
|
After Width: | Height: | Size: 1.8 KiB |
|
After Width: | Height: | Size: 417 B |
|
After Width: | Height: | Size: 706 B |
|
After Width: | Height: | Size: 434 B |
|
After Width: | Height: | Size: 430 B |
|
After Width: | Height: | Size: 420 B |
|
After Width: | Height: | Size: 432 B |
|
After Width: | Height: | Size: 410 B |
|
After Width: | Height: | Size: 387 B |
|
After Width: | Height: | Size: 404 B |
|
After Width: | Height: | Size: 431 B |
|
After Width: | Height: | Size: 590 B |
|
After Width: | Height: | Size: 577 B |
|
After Width: | Height: | Size: 591 B |
|
After Width: | Height: | Size: 595 B |
|
After Width: | Height: | Size: 513 B |
|
After Width: | Height: | Size: 510 B |
|
After Width: | Height: | Size: 592 B |
|
After Width: | Height: | Size: 596 B |
|
After Width: | Height: | Size: 849 B |
|
After Width: | Height: | Size: 862 B |
|
After Width: | Height: | Size: 862 B |
|
After Width: | Height: | Size: 872 B |