Asteroid B612 https://www.b612.me/ zh-CN B612星球 Thu, 18 Jan 2024 22:59:00 +0800 Thu, 18 Jan 2024 22:59:00 +0800 新冠对我们的身体造成了哪些危害 https://www.b612.me/sarscov2/256.html https://www.b612.me/sarscov2/256.html Thu, 18 Jan 2024 22:59:00 +0800 admin

原文地址:https://www.panaccindex.info/p/what-sars-cov-2-does-to-the-body-548

翻译前言

新冠并没有消失,疫情也不是结束了,而是刚刚开始……

曾经有个这样的苏联笑话:

列宁,斯大林,赫鲁晓夫,勃列日涅夫和戈尔巴乔夫(前苏联五代领导人)一起坐火车出行。行进间火车急刹车,因为前面没铁轨了。
…………中略…………
勃列日涅夫把车厢的窗帘拉上,坐在那里前后晃动,假装火车还在行进。
…………后略…………

在各国超额死亡率一直处于高位的今天,不顾一切地恢复“正常”生活,想要回到2019年前的幸福生活的人们,何尝又不是新时代的苏联笑话中的勃列日涅夫呢?

“时代的一粒灰,落在个人头上就是一座山”--- 这个20年初的“名言”,如今又应验在多少陷入悲痛无法挽回的家庭之中呢。

上海市某镇新型冠状病毒感染管控放开后居民超额死亡及减寿年数分析
estimate of COVID-19 Deaths, China, December 2022–February 2023

生命只有一次,健康是人类进行各项社会活动的基础。新冠是我们这个时代的肺结核,它终将会成为悬在每个人头上的达摩克利斯之剑。

本文为panaccindex.info上《What SARS-CoV-2 Does to the Body》一文的中文翻译,大部分为机翻+校验,所有版权归原作者所有;本文存在的目的只是为了警示自我。

正文

d8692360-37bd-469e-bcb1-a799cc6e7119_680x614.jpg

来自德国卫生部长的一项事实。

在JN.1毒株的肆虐中,我们迎来了大型假期,步入了2024年。在疫苗加强针接种率低,几乎没有人戴口罩的背景下,许多美国人在假日活动中将会把一种致命且可能致残的病毒带回家,并在接下来的几个月里发现自己可能成为了残疾人。
紧接着我们之前的汇编研究(2023年7月发布与2022年11月发布),在此关键时刻,我们继续更新发布了这份关于SARS-CoV-2(病毒)和COVID-19(疾病)如何伤害人体的最新医学研究汇编。

ae3b6a85-df66-4d1b-b2b4-8fef19dd4534_910x382.jpg

艾米丽·奥斯特(Emily Oster)没有评估医学研究质量的医学或科学资格。 她只不过是一个花哨的 Substack 骗子。

某些支持病毒的怪人,如布朗大学经济学家 Emily Oster、伦敦大学学院的 Francois Balloux 和加州大学旧金山分校的 Vinay Prasad,对记录新冠病毒 (COVID-19) 造成的长期健康并发症的大量研究进行了攻击;在新闻媒体和社交媒体上进行游说,将其描述为只不过是轻微的流感或感冒,并攻击了全球研究人员的道德和能力。不幸的是,哪里有烟,哪里就有火——现实正在打破数百万人对新冠的否认文化。

由于各国政府集体将本国公民抛弃在这种新病毒的感染之下,他们将被迫了解自己在最近一波淹没在瘟疫中的“常态”里可能出现的新的严重并发症。正文按字母顺序分为几个部分,请随意使用“Ctrl+F”搜索任何感兴趣的特定主题。

儿童与新冠肺炎 (COVID-19)

bc43644f-5f13-474c-9e13-86abfc8edf1b_850x1163.jpg

上图摘自“儿童和青少年的长新冠:系统评价和荟萃分析”

“感染12个月后,20.3%感染新冠的儿童和 5.9% 的对照组儿童被诊断为神经发育迟缓”(国际传染病学会)

儿童和青少年的长新冠:系统回顾和荟萃分析 (Scientific Reports)

一名青少年在感染新冠病毒后双侧声带麻痹需要长期气管切开术(美国儿科学会)

40% 的儿童在症状消退后仍然具有传染性(临床传染病,牛津)

“2022 年,COVID-19 与 0-5 岁儿童 RSV 感染风险显着增加相关”(PubMed Central)

“无论疾病严重程度,所有感染新冠的儿童都会出现血管损伤”(费城儿童医院)

“2021 年 7 月至 12 月期间,英格兰取消了新冠限制后,15 岁以下儿童的侵袭性肺炎球菌疾病发病率更高”(新发传染病)

美国 300,000 名儿童因新冠失去了主要照顾者(伦敦帝国学院)

儿科新冠感染后的肺功能障碍(放射学、RSNA)

不是“小成年人”:专家称儿童长期感染新冠病毒的人数被低估、误诊 (CIDRAP)

扁桃体是儿童中新冠病毒持续存在的主要部位(微生物学谱,美国微生物学会)

认知与神经功能障碍

image.png

大脑内外新冠的深远影响

神经炎症:将炎症细胞引入大脑,并激活大脑自身的免疫细胞。

新冠病毒刺突蛋白或病毒碎片进入大脑,引发或进一步加剧炎症。

受损的血管和血管内壁可能导致微血栓或微出血,从而导致中风、记忆问题和其他并发症。

常见轻度影响:

  • 记忆问题或脑雾
  • 头晕
  • 肌肉和关节疼痛

中度影响

  • 中风
  • 麻木和刺痛感
  • 自主神经系统紊乱
  • 头痛和偏头痛
  • 癫痫和癫痫发作
  • 肌肉不自主抽搐

罕见影响

  • 脑炎
  • 脊髓炎
  • 长期肌肉无力
  • 类帕金森病
  • 单侧面部下垂

“新冠能够以多种方式损害大脑……大脑炎症……新的心理疾病的发生,如严重的抑郁症或焦虑症……精神病……损害大脑的自主神经系统。”(哈佛健康出版社)

新冠病毒导致大脑损伤:采用AZD8797进行治疗干预(《显微镜与微观分析》,牛津学术)

老年人在新冠病毒感染恢复后遭受持续的认知损害(新医学生命科学)

“……众所周知,新冠会导致全身炎症和大脑神经炎症”(《脑科学MDPI》)

“……新冠患者在初始诊断确诊360天内,新确诊为阿尔茨海默病的风险显著增加……”(HMS公共访问)

新冠在血液中留下大脑损伤的标记(《Nature》)

“新冠病毒感染与新确诊的精神分裂症谱系和精神疾病的增加有关”(medRxiv)

新冠病毒对大脑的感染:终身后果(Open Access Government)

拉丁美洲新冠病毒感染后新的每日持续性头痛:一项横向研究(BMC传染病)

长期新冠与严重的认知减慢有关(medRxiv)

“……灰质厚度……在急性期显著减少。”(JAMA网络)

新冠病毒对女性的神经学风险:支撑性别差异的复杂免疫学(免疫学前沿)

与新冠病毒相关的大脑功能障碍(MSD手册)

新冠病毒感染和病毒融合蛋白导致神经元和胶质融合,妨碍神经元活动(Science Advances)

“……观察到的吞吐量变化相当于正常10.6年的老化水平及轻度认知损害负担增加59.8%。”(medRxiv)

“有些新冠感染者的小血管破裂导致大脑出血(所谓的微出血)。”(国家神经疾病和中风研究所)

“临床数据也支持这种观点,即阿尔茨海默病可以在新冠患者中启动或恶化。”(Acta Neurologica Belgica)

眼睛

“新冠感染前后,平均视网膜神经纤维层厚度分别为119.33 ± 3.88 和 117.50 ± 3.92 微米,这表示了一个统计学上的显著减少(P < 0.001)。”(法国眼科杂志)

视网膜异常与新冠感染(美国眼科学会)

“38名患者中有12名的眼部表现符合结膜炎。”(JAMA眼科)

心脏与心血管

2d06e35d-cf73-4149-877e-1a23b49c2359_680x256.jpg

新冠感染后的内皮损伤

“感染新冠后,患者可能因心脏中持续的病毒感染而有更高的心力衰竭风险。” (The Mainichi)

“病毒可以直接影响心脏,例如通过炎症心肌或其周围的层。它也可能导致供给心脏的神经纤维失调,无论是通过直接影响还是通过免疫系统激活。” (Prevention)

“患有慢性心肌病的患者可能在他们的心脏中有持续的病毒感染,特别是新冠病毒,这种病毒主要攻击在人心脏中高度表达的ACE2受体。” (iScience)

新冠感染后的运动耐受性不良与骨骼肌的毛细血管改变和免疫调节失常有关 (Acta Neuropathologica Comms)

“…多种表现形式的心脏并发症,许多可以持续数月甚至数年。” (BMC Medicine)

新冠病毒触发冠状血管的炎症反应 (Skeptical Raptor)

先前的新冠感染与急性冠状动脉综合症中持续和更高的血栓负荷有关 (European Heart Journal, Oxford Academic)

新冠造成的损害在心脏中持续存在 (Harvard Medicine)

新冠病毒感染触发人冠状血管的促动脉硬化炎症反应 (Nature Cardiovascular Research)

“…新冠患者表现出新发心血管和脑血管并发症的增加风险和过度负担。对于完全接种疫苗和增强免疫的个体,风险按等级减少。” (Clinical Infectious Diseases, Oxford Academic)

免疫系统

8f44ea4f-77ff-4b24-b292-35a18de0bc82_960x886.jpg

来自“单细胞RNA测序揭示了新冠感染和恢复期间免疫细胞内部的微生物多样性”

“单细胞RNA测序揭示了新冠感染和恢复期间免疫细胞内部的微生物多样性” (iScience)

新冠病毒 BA.2·86到JN.1在强烈的免疫压力下快速演变 (The Lancet Infectious Diseases)

新冠病毒利用CD4感染T助手淋巴细胞 (eLife)

“严重急性新冠病毒感染患者显示出T细胞激活增加和随后的T细胞耗竭。” (Memorial Sloan Kettering Cancer Center)

获得性免疫缺陷综合症(俗称艾滋病)与新冠病毒 N基因型的相关性 (ScienceDirect)

新冠感染后自身免疫疾病的高风险 (Nature Reviews Rheumatology)

T细胞和B细胞的数量减少与非重症新冠患者中持续存在的SARS-CoV-2有关 (Scientific Reports, Nature)

新冠感染能通过失调免疫系统导致宫颈上皮内肿瘤的快速进展:一种假设 (Journal of Reproductive Immunology)

肠道对严重新冠感染免疫反应的持久影响 (Infectious Disease Special Edition)

新冠感染削弱免疫细胞对疫苗的反应 (National Institute of Allergy & Infectious Diseases)

T细胞交叉反应与新冠感染触发的类自身免疫性肝炎 (hLife)

肝与肾

“…心脏、肾脏、肝脏和淋巴结中的线粒体功能仍受损,可能导致严重的COVID-19病理变化。” (Science Translational Medicine)

新的超声研究显示,新冠感染后10个月肝硬度增加 (Diagnostic Imaging)

“长新冠患者在感染日期的一年内,eGFR(肾功能)大幅下降” (Nephrology Dialysis Transplantation, Oxford Academic)

“在新冠感染后急性期,生存下来的患者表现出肾脏不良结果的增加风险。” (Clinical Epidemiology, Journal of the American Society of Nephrology)

长新冠和残疾

3c27c21d-1d92-4c6a-a724-63b4f40a3f27_494x385.jpg

英国ONS劳动力市场调查显示,由于长期疾病导致的失业人数自2020年以来持续上升,且没有平稳下来。

“… 长新冠的患病率在感染两年后为30%...疲劳,认知障碍和疼痛...焦虑,抑郁和睡眠问题的患病率…” (Journal of Infection)

长新冠会剥夺你的健康,你的财富——然后它会影响你的婚姻 (ABC News)

[在非洲] “任何新冠后遗症症状的发病率为48.6%(95% CI 37.4–59.8),其中精神疾病最为常见,特别是创伤后压力障碍的累积发病率达到25%” (Scientific Reports, Nature)

PASC相关运动不耐受的心肺血流动力学表型差异 (ERJ Open Research)

“在只有一次急性新冠发作的518人中,32.2%满足WHO对[新冠后遗症]的定义” (medRxiv)

“在18个月的随访中,与季节性流感相比,新冠对照组的死亡风险增加” (The Lancet Infectious Diseases)

长新冠对美国家庭的经济影响 (Medriva)

“大约350万加拿大成年人报告在新冠感染后出现长期症状;210万人报告他们在2023年6月仍在经历这些症状。” (Statistics Canada)

新的MRI揭示了长新冠患者的大脑变化 (Radiological Society of North America)

“在完成2年和3年随访的1359名新冠康复者中,有728人(54%)在症状出现后3年内至少有一个后续症状” (Respiratory Medicine, The Lancet)

“…[长新冠]的患者更有可能在颈部超声中显示迷走神经的增厚和高回声” (Clinical Microbiology and Infection)

“超过50%的长新冠患者在使用任何结果测量时都未见改善。” (International Journal of Infectious Diseases)

“[在美国] 14%的人报告曾经在某个时点患有长新冠。” (PLOS One)

长新冠的免疫学分型:总体低度炎症和T淋巴细胞衰老,以及与疲劳严重程度增加相关的单核细胞激活增加 (Front Immunology, PubMed)

长新冠:医生们的生活被他们在工作中感染的疾病摧毁 (British Medical Journal)

总体死亡率

c56b10c2-6f45-402a-a24e-5a37c03a6903_931x353.jpg

上图来自“州政府党派关系与COVID-19大流行前后州死亡率的关联”

“…新冠感染者的住院治疗风险与死亡率和几乎每个器官的不良健康结果的长期风险增加有关” (The Lancet)

“感染新冠病毒并发展为成人呼吸窘迫综合症(ARDS)的人常常会积累过多的细胞外基质沉积,导致肺部、心脏和神经纤维化,从而恶化器官功能” (PubMed Central)

州政府党派关系与新冠大流行前后州死亡率的关联 (Milbank Quarterly)

胰腺

"SARS-COV-2病毒可以侵入胰腺,并可能对胰腺实质造成直接和间接的损伤。" (Pancreatology, Science Direct)

妊娠

通过胎儿MRI评估新冠病毒对产前肺部生长的影响 (Respiratory Medicine, The Lancet)

怀孕期间感染新冠后,在新生儿大便中检测到新冠病毒 (Pediatric Research, Nature)

病例研究显示新冠病毒可以通过胎盘从母亲传播给婴儿,导致脑损伤 (迈阿密大学)

新冠再感染

“…再感染会导致比第一次感染更多的健康风险,包括全因死亡率、住院率和在广泛的器官系统中的后遗症。” (Nature Medicine)

重复的奥密克戎暴露可以覆盖祖先SARS-CoV-2的免疫印记 (Nature)

早期奥密克戎感染与长期护理和退休设施中的老年人再感染风险增加有关 (eClinicalMedicine)

第二次感染增加长新冠风险 (Medscape)

生殖系统

“感染新冠的男性可能会有精子计数的下降。前列腺和男性生殖系统已受到影响...流产在女性中变得常见。” (Times of India)

精液蛋白质组学揭示了从新冠恢复后与生育相关的蛋白质的变化 (Frontiers in Physiology)

冰山一角:勃起功能障碍与新冠 (International Journal of Impotence Research, Nature)

与SARS-CoV-2感染相关的睾丸病理改变 (Frontiers in Reproductive Health)

SARS-CoV-2进入人类Leydig细胞并影响体外睾酮产生 (Cells MDPI)

新冠患者勃起功能障碍的比率增加 (Journal of Endocrinol Investigations)

新冠感染阴茎、睾丸和前列腺 - 导致疼痛、勃起功能障碍、精子计数减少 (SciTechDaily)

长新冠综合征:新冠感染幸存者中的心理和性功能障碍 (Annals of Medicine & Surgery)

“病例报告提示,新冠感染可能与卵巢健康的长期下降有关,包括早期卵巢功能不全(POI),即40岁前卵巢正常功能的丧失。” (Frontiers in Rehabilitation Sciences)

皮肤

来自“新冠病毒引起的血管炎性皮肤病变与自噬体中大量刺突蛋白沉积有关”

2ccc2789-fa7c-4b94-81e5-77d72521edd7_2657x1401.jpg

新冠和皮肤表现:对已发表文献的回顾 (Wiley - PMC COVID-19 Collection)

新冠病毒引起的血管炎性皮肤病变与自噬体中大量刺突蛋白沉积有关 (Journal of Investigative Dermatology)

病毒持续性

f7ae0963-a4e4-443c-821d-0771b06f7362_1164x517.jpg

新冠病毒 (绿色) 使用细胞扩展来感染另一个细胞 (粉红色的核) 以逃避免疫系统检测。

“…在症状发作后的230天内,多个解剖部位,包括整个大脑内,都可以持续检测到SARS-CoV-2 RNA…” (Nature)

“…在一些个体的肺部可以发现新冠病毒,甚至在感染后的18个月后仍可发现,但其持续存在似乎与先天免疫的失败有关” (CEA)

“新冠病毒可以进入正常人肠道微生物群的细菌细胞,并合成RNA和病毒肽。” (F1000 Research)

多模态分子成像揭示了组织基础的T细胞激活和病毒RNA持续存在,这种状态可以在感染恢复后持续长达2年 (medRxiv)

肺泡巨噬细胞中的新冠病毒持续性受到IFN-γ和NK细胞的控制 (Nature Immunology)

急性后新冠的特征是炎症性肠病中的肠道病毒抗原持续存在 (Gastroenterology)

长新冠与病毒持久性、血清素下降有关 (JAMA Network)

后记

这就是了,朋友们。再一次,超过100项研究详细地描述了新冠对人体的许多长期损害 - 任何声称新冠只是一种可以每年多次、反复地损害你的健康的“普通感冒”或“流感”的人,都是严重误解并正在积极误导你。

请务必广泛分享这篇文章 - 因为在这个假期高峰期后,许多美国人可能会面临与新的SARS-CoV-2相关的健康问题。N95呼吸器可以有效防护空气传播,如果可以的话,一定要接种最新的新冠疫苗加强针。

为了以积极的心态结束这篇文章,以下是一些关于阻止新冠病毒空气传播和预防新冠感染的最新研究。结果显示,个人防护设备确实有效!科学证据已经清楚,现在只需要在全美的学校、医院和工作场所实施这些措施。

COVID-19预防

e3174154-7310-48ae-9f3e-421347d114e7_604x680.jpg

来自“外科口罩对于语音练习产生的呼出气溶胶和液滴的过滤效率”

口罩有效!- 研究收集 (通过Twitter上的MarieSnyder27)

病房空气过滤器几乎可以去除所有空气中的新冠病毒 (NHS Cambridge University)

空气过滤对新冠肺炎(COVID-19) 高发病房中空气传播的新冠病毒 (SARS-CoV-2) 和其他微生物生物气溶胶的去除能力研究 (Clinical Infectious Diseases, Oxford Academic)

关于新冠大流行期间病毒干扰的概述 (Frontiers in Pediatrics)

下一代可吸入的干粉新冠疫苗 (Nature)

黏膜增强可以增强对恒河猴SARS-CoV-2的疫苗保护 (Nature)

新冠加强针:如果美国能够匹敌以色列的速度和接种率,预计可以挽救29000个美国人的生命 (HealthAffairs)

“…未能立即认识到控制新冠空气传播的紧迫需要…代表了一个重大的医疗错误,导致了‘大量生命的丧失’。” (MetaArXiv)

在日托中心使用空气净化器可将孩子的生病天数减少三分之一 (YLE News)

外科口罩对于语音练习产生的呼出气溶胶和液滴的过滤效率 (Aerosol Science and Technology)

“…口罩强制令是一种有效的降低在颁布地区及其周边地区传播的方式。” (犹他大学)

HEPA过滤减少新冠病毒的传播并防止院内感染:一个行动呼吁 (BC Medical Journal)

在工业工作场所进行鼻部光消毒以抑制新冠传播 (Photodiagnosis & Photodynamic Therapy)

]]>
0 https://www.b612.me/sarscov2/256.html#comments https://www.b612.me/feed/sarscov2/256.html
佳明WatchAPP编写体验 https://www.b612.me/code/248.html https://www.b612.me/code/248.html Sun, 31 Dec 2023 13:49:00 +0800 admin 背景

双十一期间,买了块佳明 Instinct 2X,不过应用商店内没有多少有趣的适配App,于是便想自己折腾一下。
因为我买的是国行手表,所以GPS输出的经纬度信号都是偏移后的GCJ02坐标,而不是国际惯用的WGS84;另一方面,手表带有磁传感器和加速度传感器,所以我便有了这样的想法:

  1. 坐标纠偏,并且可以选择坐标系和显示格式
  2. 增加一点天文功能,比如晚上出去看到一颗星星,用手表对准它,便能够知道是什么星星;显示太阳月亮的天文信息等

安装

佳明手表上的所有App都使用MonkeyC这个弱类型的语言来编写,按照官方指引下载SDK,再在vs code上安装对应的Monkyec插件,简单配置下JDK即可,不过调试的时候与模拟器的通信老是失败,最后发现还是那个老生常谈的问题:开了HyperV导致的,重启下winnat服务就能解决这个问题。

Hello World

新建一个空Project,插件会在source文件夹中默认初始化四个文件:App.mc Delegate.mc MenuDelegate.mc与view.mc;这四个文件的作用分别如下

App.mc  #程序入口文件,在getInitialView函数中初始化view和对应的Delegate
Delegate.mc #用于响应用户按键或触屏指令,默认生成的文件只带onMenu()函数,代表用户长按菜单键的动作,也可以自行添加其他函数来响应其他按键的动作:如onSelect() onPreviousPage()等
MenuDelegate.mc #用户响应用户对菜单的指令,和Delegate.mc类似,只不过是菜单的专属响应class
View.mc #用于页面布局

踩坑

搞清楚基础的编写逻辑后,便可以着手设计应用逻辑,本想着完整重写github.com/Starainrt/astro我的这个package到monkeyc上,但是验证的时候发现如下的问题:

  1. 内存限制
  2. 指令执行长度限制
  3. Double类型计算结果十分不精准

内存限制

智能手表其实也算个嵌入式硬件,与PC不同,这些设备的内存都比较小,稍有不注意就stackOverflow,对于佳明手表,每个型号的手表配置在: {SDK Folder}/Devices/{型号}/compiler.json 中定义,对于我的本能2X,相应的限制如下:

 "appTypes": [
        {
            "memoryLimit": 32768,
            "type": "background"
        },
        {
            "memoryLimit": 32768,
            "type": "datafield"
        },
        {
            "memoryLimit": 32768,
            "type": "glance"
        },
        {
            "memoryLimit": 98304,
            "type": "watchApp"
        },
        {
            "memoryLimit": 65536,
            "type": "watchFace"
        },
        {
            "memoryLimit": 65536,
            "type": "widget"
        }

可以看到,即便是watchAPP,最大也只给到了90多Kb大小的内存,而对于一个完整的VSOP87算法,每个星体的迭代项都高达至少400多项,以double类型存储的话,每个星体至少也需要500K以上的内存。

针对这个限制,可行的解决思路是降低迭代精度,当我们把精度从完整的0.01角秒增大到1角秒时,所需的迭代系数只需要几百项就够了,这大大低于内存限制值。而且对于手表,1角秒的精度也是完全够用的。

指令长度限制

但即便减少了精度,每次根据时间算出黄经黄炜也是需要上百次迭代计算的。但是对于佳明手表,每个流程所包含的代码执行长度也是有限制的,如下图,我想在启动时执行10次计算太阳高度的函数,前8此都能正常返回,但是第9次便报错: Code Executed Too Long

屏幕截图 2023-12-31 150858.png

对于这个问题,在论坛中已有讨论,基本只能通过修改算法规避;但是对于我这个场景基本是无解的,因为计算日月恒星升落必然涉及大量的计算,如牛顿迭代公式。

Double类型计算结果十分不精准

这个问题是压垮本地化算法这条路的最后一根稻草!
让我们做一个测试: 0.123456789*0.987654321
对于大多数编程语言,Double类型的数据能提供15位小数精度,上面算式的结果应当为:0.1219326311126353
而在monkeyc中,结果如下:

屏幕截图 2023-12-31 152322.png

对比
0.1219326311126353
0.121932634037635879

可以看出,monkeyc中的Double只能提供8位小数精度,在天文计算中,这是远远不够的,因为在天文计算中,常常用儒略千年数作为最基本的单位参与计算,而8位小数,相当于千年数中的31秒,误差达到半分钟,可以说已经是非常大了。

更换思路

既然本地化算法行不通,那只能依靠上位机了,佳明的SDK中Communication类提供了makeWebRequest功能,那一切就好说了,可以用服务器搭一个网关,手表将数据传送到服务器上,服务器计算后返回结果,手表再进行展示。

这种方法的缺陷在于,手表必须一直链接手机,且手机处于强网环境才能得知结果,整体链路太长,稳定性不佳。稍微优化一下,可以准备两套尚未程序,一套放在公网上,在强网环境使用,另一套放在手机上,跑在termux中,这样手表只有连接到手机上便能够直接得到数据。

算法

GPS纠偏有现成的算法,且算法比较简单,直接本地使用即可。

太阳和月亮的天文坐标用算法便可以直接算出,稍微复杂一点的便是星星算法,很多手机APP也提供了类似的AR功能,但对于手表来说,思路也是相近的,整体思路如下

  1. 首先,将手表对准了星星,便能通过磁传感器获取到方位角,通过加速度传感器,获得手表的倾角,也就类似等于星星的高度角。
  2. 通过GPS,能够获取到观测者的经纬度
  3. 结合时间与经度,获取到当地恒星时
  4. 通过如上方位角,高度角,经纬度与恒星时,便可以得知这个方位角与高度角对应的天球座标。
  5. 在城市中,人眼看到的星星大多都是视星等3等以下的星星,遍历这100多颗星星,按照亮度与天球座标的拟合度排序,再展示给用户

效果:

屏幕截图 2023-12-31 154151.png

屏幕截图 2023-12-31 154230.png

屏幕截图 2023-12-31 154510.png

]]>
0 https://www.b612.me/code/248.html#comments https://www.b612.me/feed/code/248.html
得新冠的感受 https://www.b612.me/heart/244.html https://www.b612.me/heart/244.html Sat, 31 Dec 2022 17:38:01 +0800 admin 年底了,总结下这10天来的病程。
19号凌晨两点,突然觉得巨冷无比,尤其是背部,火速把电热毯开到大,空调开到最热,过半小时后才缓解,这也许是前兆吧。
随后的两天,身边的同事一个接一个阳,我心里也陷入巨大的焦虑中……
21日下午6点,感觉心率开始莫名增快,量了下体温,37.1度。晚间11点睡前,再量体温,已经升到了37.5度。
第二天凌晨1点,体温升到了38度,上午8点醒来,体温已经升到了38.7度,吃了一片500mg对乙酰氨基酚,起床,洗鼻,用西吡氯铵漱口,心率很快,全天在130+。
吃完对乙酰氨基酚后,体温在随后4小时内下降到38.1度,四小时后,又回升到39.1度。下午两点,又吃了一片对乙酰氨基酚,体温同样又经历了一个过山车的过程。
晚上,洗鼻,西吡氯铵漱口,睡前吃对乙酰氨基酚,睡觉。
23日起来,心率仍然很快,全天120+,体温则维持在38.4左右,白天除了洗鼻漱口外,没有吃药,晚上睡前一粒对乙酰氨基酚。
24日,心率降到了95+,体温全天则维持在37.2~37.4度之间,感觉有点乏力,开始鼻塞,嗓子倒是不怎么疼。
25日,心率维持在85+,体温则恢复正常到36.6,开始干咳,鼻塞,晚上吃了右美沙芬。
26日,心率降到65+,基本正常,鼻塞好转,咳嗽就开始厉害,仍然是嗓子痒带来的干咳,嗓子不疼,晚上明显感觉嗅觉退化,只能闻到究竟,枇杷膏,醋等刺激性气味。
27日,嗅觉好转,症状只剩下了咳嗽。
28~31日,咳嗽不停但是逐渐好转,剩下唯一的感觉就是累。

总的来说,这次新冠发烧没有19年那次上感严重,嗓子基本上不怎么疼,咳嗽成都和19年相当,这些呼吸道症状都是在可忍受阈值内,但是心率变化明显,身上明显感觉比19年乏力很多,真的让我不想再得第二次了!

]]>
0 https://www.b612.me/heart/244.html#comments https://www.b612.me/feed/heart/244.html
Golang实现“请按任意键继续”“密码自定义掩码”等操作 https://www.b612.me/golang/240.html https://www.b612.me/golang/240.html Sat, 14 Aug 2021 10:32:00 +0800 admin 前言

好久没写东西了,所以翻出老东西继续写点水水的玩意儿QAQ
核心原理这个包github.com/howeyc/gopass的代码实现已经写的很清晰了,其实就是正确使用golang.org/x/crypto/ssh/terminal中MakeRaw功能即可。

实现

“请按任意键继续”是windows bat中很常见的一句话。
这里关键点在于任意键,Go中用fmt.Scan等函数程序处理输入都是在按下回车键后才进入我们的处理逻辑的,所以这里就要用到terminal.MakeRaw函数,通过传入stdin的文件描述符,亲自处理每个传进来的字节。
同样的,因为用MakeRaw能够处理每个传进来的字节,所以我们不仅能实现按任意键继续,也能实现按指定的字符后继续

直接贴代码吧,加上注释,代码扔在了https://github.com/Starainrt/stario


// StopUntil 按下指定的字符函数才会返回,如果不是指定的字符,返回error(repear=false)
// 或阻塞住直到按下指定的字符(repeat=true)
// hint提示文本,trigger指定的字符,repeat是否允许多次重试
func StopUntil(hint string, trigger string, repeat bool) error {
    pressLen := len([]rune(trigger))
    if trigger == "" {
        pressLen = 1
    }
        //这里获取stdin标准输入的文件描述符
    fd := int(os.Stdin.Fd())
    if hint != "" {
                //这里打印自定义提示,如:“请按任意键继续”
        fmt.Print(hint)
    }
        // 进入Raw模式
    state, err := terminal.MakeRaw(fd)
    if err != nil {
        return err
    }
       //defer退出Raw模式
    defer terminal.Restore(fd, state)
    inputReader := bufio.NewReader(os.Stdin)
    //ioBuf := make([]byte, pressLen)
    i := 0
    for {
                //这里用了Rune,是考虑到中文字符
        b, _, err := inputReader.ReadRune()
        if err != nil {
            return err
        }
                //指定的字符为空,按下任意键直接返回
        if trigger == "" {
            break
        }
        if b == []rune(trigger)[i] {
            i++
            if i == pressLen {
                break
            }
            continue
        }
        i = 0
        if hint != "" && repeat {
            fmt.Print("\r\n")
            fmt.Print(hint)
        }
    }
    return nil
}

测试代码:

package main

import (
    "b612.me/stario"
    "fmt"
)

func main() {
    if err := stario.StopUntil("请按任意键继续", "", false); err != nil {
        panic(err)
    }
    fmt.Println("\ncontinued")
    if err := stario.StopUntil("请按b612继续", "b612", true); err != nil {
        panic(err)
    }
    fmt.Println("\nbye bye")
}

效果:

屏幕截图 2021-08-14 105238.png

密码掩码的实现原理一样,差别就是读取到输入的时候屏幕上打印*或者其他自定义字符,实现可参考gopass包
直接的简单的实现可参考下面的代码,代码同样扔在了https://github.com/Starainrt/stario

type InputMsg struct {
    msg string
    err error
}

func passwd(hint string, defaultVal string, mask string) InputMsg {
    var ioBuf []rune
    if hint != "" {
        fmt.Print(hint)
    }
    if strings.Index(hint, "\n") >= 0 {
        hint = strings.TrimSpace(hint[strings.LastIndex(hint, "\n"):])
    }
    fd := int(os.Stdin.Fd())
    state, err := terminal.MakeRaw(fd)
    if err != nil {
        return InputMsg{"", err}
    }
    defer fmt.Println()
    defer terminal.Restore(fd, state)
    inputReader := bufio.NewReader(os.Stdin)
    for {
        b, _, err := inputReader.ReadRune()
        if err != nil {
            return InputMsg{"", err}
        }
        if b == 0x0d {
            strValue := strings.TrimSpace(string(ioBuf))
            if len(strValue) == 0 {
                strValue = defaultVal
            }
            return InputMsg{strValue, nil}
        }
        if b == 0x08 || b == 0x7F {
            if len(ioBuf) > 0 {
                ioBuf = ioBuf[:len(ioBuf)-1]
            }
            fmt.Print("\r")
            for i := 0; i < len(ioBuf)+2+len(hint); i++ {
                fmt.Print(" ")
            }
        } else {
            ioBuf = append(ioBuf, b)
        }
        fmt.Print("\r")
        if hint != "" {
            fmt.Print(hint)
        }
        for i := 0; i < len(ioBuf); i++ {
            fmt.Print(mask)
        }
    }
}

测试代码:

package main

import (
    "b612.me/stario"
    "fmt"
)

func main() {
    //设置掩码为*
    fmt.Println("输入的密码为:",
        stario.PasswdWithMask("请输入密码:", "", "*").MustString())
    //不设置掩码,输入密码时不显示
    fmt.Println("输入的密码为:",
        stario.PasswdWithMask("请输入密码:", "", "").MustString())
    //设置掩码为@
    fmt.Println("输入的密码为:",
        stario.PasswdWithMask("请输入密码:", "", "@").MustString())
}

效果:
屏幕截图 2021-08-14 110128.png

]]>
1 https://www.b612.me/golang/240.html#comments https://www.b612.me/feed/golang/240.html
批量修改GIF的循环次数 https://www.b612.me/golang/232.html https://www.b612.me/golang/232.html Thu, 25 Feb 2021 09:14:00 +0800 admin 前言

最近收获了不少APNG格式的兔子表情包,用APNG2GIF工具批量转成gif后,发现在微信上,只能播放一次!于是便去研究如何批量修改gif的循环次数。
搜索引擎输入:批量修改gif循环次数,并没有找到合适的教程。搜到的结果要么是用PS改次数的教程,要么是针对单个gif的工具,无法批量。虽然我得到了300多张可爱的兔兔,但是要我一张一张手动去改,怕不也要累死……

研究

于是便开始从GIF格式本身开始研究,在维基百科 界面,找到了很多有用的信息。

从维基百科中得以知道:gif的循环次数实现在GIF89A标准的Application Extension的block中,截取百科中的相关片段如下:


byte#  hexadecimal  text or
(hex)               value     Meaning
0:     47 49 46
       38 39 61     GIF89a    Header
                              Logical Screen Descriptor
6:     90 01        400        - width in pixels
8:     90 01        400        - height in pixels
A:     F7                      - GCT follows for 256 colors with resolution 3 x 8bits/primary
B:     00           0          - background color #0
C:     00                      - default pixel aspect ratio
D:                            Global Color Table
:
30D:   21 FF                  Application Extension block
30F:   0B           11         - eleven bytes of data follow
310:   4E 45 54
       53 43 41
       50 45        NETSCAPE   - 8-character application name
       32 2E 30     2.0        - application "authentication code"
31B:   03           3          - three more bytes of data
31C:   01           1          - index of the current data sub-block (always 1 for the NETSCAPE block)
31D:   FF FF        65535      - unsigned number of repetitions
31F:   00                      - end of App Extension block
320:   21 F9                  Graphic Control Extension for frame #1
322:   04           4          - four bytes in the current block
323:   04           000.....   - reserved; 5 lower bits are bit field
                    ...001..   - disposal method 1: do not dispose
                    ......0.   - no user input
                    .......0   - transparent color is not given
324:   09 00                   - 0.09 sec delay before painting next frame
326:   FF                      - transparent color index (unused in this frame)
327:   00                      - end of GCE block
328:   2C                     Image Descriptor of frame #1
329:   00 00 00 00  (0,0)      - NW corner of frame at 0, 0
32D:   90 01 90 01  (400,400)  - Frame width and height: 400 × 400
331:   00                      - no local color table; no interlace
332:   08           8         LZW min code size; Image Data of frame #1 beginning 
333:   FF           255        - 255 bytes of LZW encoded image data follow
334:                data
433:   FF           255        - 255 bytes of LZW encoded image data follow
                    data
                     :
92C0:  00                      - end of LZW data for this frame
92C1:  21 F9                  Graphic Control Extension for frame #2
 :                                                            :
EDABD: 21 F9                  Graphic Control Extension for frame #44
 :
F48F5: 3B                     File terminator

我们可以看到,其中的30D行,定义Application Extension头。31D行,定义循环次数。

再去相关网站查看对Application Extension的定义,截取如下:

            i) Extension Introducer - Defines this block as an extension. This
            field contains the fixed value 0x21.

            ii) Application Extension Label - Identifies the block as an
            Application Extension. This field contains the fixed value 0xFF.

            iii) Block Size - Number of bytes in this extension block,
            following the Block Size field, up to but not including the
            beginning of the Application Data. This field contains the fixed
            value 11.

            iv) Application Identifier - Sequence of eight printable ASCII
            characters used to identify the application owning the Application
            Extension.

从这我们得知,我们可以通过0x21 0xFF 0x0B 这三个byte来定位到Application Extension的位置。(或者通过Identifier,一般为字符NETSCAPE)

修改与验证

由上面的信息,我们可以得到以下修改步骤:

  1. 通过0x21 0xFF 0x0B byte定位Application Extension的位置
  2. 通过Application Extension的位置找到gif的循环次数,偏移量为+16
  3. 修改循环次数为0xFF 0xFF,实现无限循环

简单的验证代码:

data, _ := ioutil.ReadFile("兔兔.gif")
index := bytes.Index(data, []byte{0x21, 0xFF, 0x0B})
fmt.Println(data[index+16 : index+18])

得到的结果为[3,0],即0x03 0x00,表明这个gif只循环了4次

修改代码

func UnlimitedGifRepetitions(path string) ([]byte, error) {
    data, err := ioutil.ReadFile(path)
    if err != nil {
        return nil, err
    }
    index := bytes.Index(data, []byte{0x21, 0xFF, 0x0B})
    if index < 0 {
        return nil, fmt.Errorf("cannot Found Gif Application Extension in %s", path)
    }
    data[index+16] = 255
    data[index+17] = 255
    return data, nil
}

修改完后,再次发微信验证下,完美无限循环!

来欣赏下兔兔:
63422932-ps.gif

]]>
1 https://www.b612.me/golang/232.html#comments https://www.b612.me/feed/golang/232.html
使用docker搭建Synapse[Matrix] https://www.b612.me/code/223.html https://www.b612.me/code/223.html Tue, 08 Dec 2020 09:29:00 +0800 admin 前言

官方的Synapse docker镜像仅给出了简单的用法,这里简单记录下自己使用docker compose来搭建synapse的过程,数据库使用postgres并同时启用redis。

搭建

首先,选择一个宿主机文件夹,用于存放synapse所有的数据,我的规划如下:

  • Synapse数据:/data/synapse/data
  • PostgreSQL数据: /data/synapse/postgres
  • Redis持久化数据: /data/synapse/redis

PostgreSQL

pg库我选择了12.5版本,选择的镜像是postgres:12.5-alpine。

  • 拉取pg镜像并初始化pg库,挂载volume到上面规划的pg数据文件夹
docker run --name postgres12 -v /data/synapse/postgres:/var/lib/postgresql/data -e   POSTGRES_PASSWORD=自定义PostgreSQL密码 -d postgres:12.5-alpine

界面会显示容器的hash值,接着执行下面的命令创建一个用于连接数据库的synapse用户并输入你的密码

docker exec -it postgres12 createuser -U postgres --pwprompt synapse_user

执行下面的语句进入psql

docker exec -it postgres12 psql -U postgres

执行下面的建库语句用于建立一个synapse库

CREATE DATABASE synapse
 ENCODING 'UTF8'
 LC_COLLATE='C'
 LC_CTYPE='C'
 template=template0
 OWNER synapse_user;

执行完毕后输入q退出
*后续连接如果有问题,可以在postgres/pg_hba.conf中添加host synapse synapse_user all trust
*具体可以参看官方的Pg搭建手册

  • 终止postgres的容器并删除
docker stop postgres12
docker rm postgres12

Synapse

接下来需要进行synapse的初始化

  • 拉取Synapse镜像并生成配置文件
docker run -it --rm \
    -v /data/synapse/data:/data \
    -e SYNAPSE_SERVER_NAME=b612.im \
    -e SYNAPSE_REPORT_STATS=yes \
    matrixdotorg/synapse:latest generate

*里面的/data/synapse/data需要更改为自己的配置文件夹地址,b612.im需要改为自己的域名,SYNAPSE_REPORT_STATS=yes表明允许匿名汇报你的Synapse信息

  • 编辑Synapse生成的配置文件

文件地址为:/data/synapse/data/homeserver.yaml
找到database配置项,注释掉原先的sqlite3配置,修改为postgres配置

database:
  name: psycopg2
  args:
    user: synapse_user
    password: synapse_user的密码
    database: synapse
    host: db
    cp_min: 5
    cp_max: 10

找到redis配置项,修改为下述内容

redis:
  enabled: true
  host: redis
  port: 6379

若需要启用email发信,找到email配置项,配置即可(记得同时配置public_baseurl

配置docker compose

/data/synapse文件夹下新建docker-compose.yml文件,内容如下

version: '3'
services:

  db:
    restart: always
    image: postgres:12.5-alpine
    shm_size: 1024mb
    networks:
      - internal_network
    healthcheck:
      test: ["CMD", "pg_isready", "-U", "postgres"]
    volumes:
      - ./postgres:/var/lib/postgresql/data

  redis:
    restart: always
    image: redis:6.0-alpine
    networks:
      - internal_network
    healthcheck:
      test: ["CMD", "redis-cli", "ping"]
    volumes:
      - ./redis:/data

  synapse:
    build: .
    image: matrixdotorg/synapse
    restart: always
    ports:
      - "127.0.0.1:8008:8008"
    depends_on:
      - db
      - redis
    networks:
      - external_network
      - internal_network
    volumes:
      - ./data:/data
      
networks:
  external_network:
  internal_network:
    internal: true

保存后,执行 docker-compose up -d 即可启动Synapse进程

配置Riot web界面

Synapse没有自带的web界面,使用Riot(已更名为element)搭建一个web界面
在(https://github.com/vector-im/element-web/releases)[https://github.com/vector-im/element-web/releases]找到最新的预编译包并下载到服务器web文件夹中。

  • 修改配置文件
cp config.sample.json config.json

修改m.homeserver中域名为自己的域名,m.identity_server建议使用https://vector.im

配置管理页面

riot(element)没有后台管理界面,可以使用synapse-admin搭建一个管理页面

docker run -d -p 8100:80 awesometechnologies/synapse-admin

配置nginx

不使用cdn

在不使用CND(如cloudflare)的情况下,配置nginx反向代理,参考如下
注意:8448端口必须开启,否则会无法与其它站通信

server {
    listen 80;
    listen [::]:80;
    server_name 你的域名;

    # Enforce HTTPS
    return 301 https://$server_name$request_uri;
}

server {
    listen 443      ssl http2;
    listen [::]:443 ssl http2;
    listen 8448 ssl default_server;
    listen [::]:8448 ssl default_server;
    server_name 你的域名;

    ssl_certificate     域名证书地址;
    ssl_certificate_key 域名私钥地址;
    root Riot所在地址;
    client_max_body_size 1024M;

    # Enable gzip but do not remove ETag headers
    gzip on;
    gzip_vary on;
    gzip_comp_level 4;
    gzip_min_length 256;
    gzip_proxied expired no-cache no-store private no_last_modified no_etag auth;
    gzip_types application/atom+xml application/javascript application/json application/ld+json application/manifest+json application/rss+xml application/vnd.geo+json application/vnd.ms-fontobject application/x-font-ttf application/x-web-app-manifest+json application/xhtml+xml application/xml font/opentype image/bmp image/svg+xml image/x-icon text/cache-manifest text/css text/plain text/vcard text/vnd.rim.location.xloc text/vtt text/x-component text/x-cross-domain-policy;
   location /.well-known/matrix/client {
        return 200 '{"m.homeserver": {"base_url": "https://你的域名"}}';
        default_type application/json;
        add_header Access-Control-Allow-Origin *;
    }  
    location ~* ^(\/_matrix|\/_synapse) {
        proxy_pass http://localhost:8008;
        proxy_set_header X-Forwarded-For $remote_addr;
        # Nginx by default only allows file uploads up to 1M in size
        # Increase client_max_body_size to match max_upload_size defined in homeserver.yaml
    }
    location /admin/ {
        #最新的synapse版本(2022-06及以后版本)中,由于静态文件在代码中使用了绝对地址,所以需要进行地址替换
        #建议使用子域名替代二级目录的访问方式
        sub_filter_once off;
    sub_filter "/static/" "/admin/static/";
        #上面两行为需要进行地址替换的部分
        proxy_pass http://localhost:8100/;
        proxy_set_header X-Forwarded-For $remote_addr;
    }

}

使用CDN

使用CDN的情况下,由于大部分CDN无法转发8448端口,故需要在nginx配置中指定通信端口为443,示例配置如下

server {
    listen 80;
    listen [::]:80;
    server_name 你的域名;

    # Enforce HTTPS
    return 301 https://$server_name$request_uri;
}

server {
    listen 443      ssl http2;
    listen [::]:443 ssl http2;
    server_name 你的域名;

    ssl_certificate     域名证书地址;
    ssl_certificate_key 域名私钥地址;
    root Riot所在地址;
    client_max_body_size 1024M;

    # Enable gzip but do not remove ETag headers
    gzip on;
    gzip_vary on;
    gzip_comp_level 4;
    gzip_min_length 256;
    gzip_proxied expired no-cache no-store private no_last_modified no_etag auth;
    gzip_types application/atom+xml application/javascript application/json application/ld+json application/manifest+json application/rss+xml application/vnd.geo+json application/vnd.ms-fontobject application/x-font-ttf application/x-web-app-manifest+json application/xhtml+xml application/xml font/opentype image/bmp image/svg+xml image/x-icon text/cache-manifest text/css text/plain text/vcard text/vnd.rim.location.xloc text/vtt text/x-component text/x-cross-domain-policy;
   location /.well-known/matrix/client {
        return 200 '{"m.homeserver": {"base_url": "https://你的域名"}}';
        default_type application/json;
        add_header Access-Control-Allow-Origin *;
    }  
   location /.well-known/matrix/server{
        return 200 '{"m.server": "你的域名:443"}';
        default_type application/json;
        add_header Access-Control-Allow-Origin *;
    }  
    location ~* ^(\/_matrix|\/_synapse) {
        proxy_pass http://localhost:8008;
        proxy_set_header X-Forwarded-For $remote_addr;
        # Nginx by default only allows file uploads up to 1M in size
        # Increase client_max_body_size to match max_upload_size defined in homeserver.yaml
    }
    location /admin/ {
        proxy_pass http://localhost:8100/;
        proxy_set_header X-Forwarded-For $remote_addr;
    }

}

配置turn服务器

turn/stun 服务器允许用户间建立语音视频连接,搭建配置方式可以参考官方的教程:https://github.com/matrix-org/synapse/blob/develop/docs/turn-howto.md

注册一位新用户

docker-compose exec  synapse register_new_matrix_user -c /data/homeserver.yaml http://localhost:8008
]]>
5 https://www.b612.me/code/223.html#comments https://www.b612.me/feed/code/223.html
[个人用]运营商PLMN手机 https://www.b612.me/default/218.html https://www.b612.me/default/218.html Tue, 11 Aug 2020 14:23:00 +0800 admin 手机的原因是某些应用(如抖音国际版)会根据PLMN判断用户归属地。使用Xposed可以指定PLMN绕过归属地限制
PLMN=MCC+MNC

中国

PLMN运营商
46000中国移动 (GSM)
46001中国联通 (GSM)
46002中国移动 (TD-S)
46003中国电信(CDMA)
46005中国电信 (CDMA)
46006中国联通 (WCDMA)
46007中国移动 (TD-S)
46008中国移动
46009中国联通
46011中国电信 (FDD-LTE)
46020中国移动 铁路专用

日本

PLMN运营商
44000SoftBank Corp.
44001UQ Communications Inc.
44002Hanshin Cable Engineering Co.,Ltd.
44003Internet Initiative Japan Inc.
44004Japan Radio Co., Ltd.
44005Wireless City Planning Inc.
44006SAKURA Internet Inc.
44007LTEX, Inc.
44008Panasonic System Solutions Japan Co., Ltd.
44009Marubeni Network Solutions Inc.
44010NTT DOCOMO, INC.
44011Rakuten Mobile, Inc.
44012Cable media waiwai Co,ltd.
44014Grape One Co., Ltd.
44015BB BACKBONE Corp.
44020SoftBank Corp.
44021SoftBank Corp.
44050KDDI CORPORATION
44051KDDI CORPORATION
44052KDDI CORPORATION
44053KDDI CORPORATION
44054KDDI CORPORATION
44070KDDI CORPORATION
44071KDDI CORPORATION
44072KDDI CORPORATION
44073KDDI CORPORATION
44074KDDI CORPORATION
44075KDDI CORPORATION
44076KDDI CORPORATION
44078Okinawa Cellular Telephone Company
44100Wireless City Planning Inc.
44101SoftBank Corp.
44110UQ Communications Inc.
44190sXGP
44191The Tokyo Organising Committee of the Olympic and Paralympic Games

参考1
参考2

]]>
0 https://www.b612.me/default/218.html#comments https://www.b612.me/feed/default/218.html
Mathjax与LaTex公式简介 https://www.b612.me/code/162.html https://www.b612.me/code/162.html Sun, 08 Sep 2019 17:12:00 +0800 admin

本文章原载于:http://mlworks.cn/posts/introduction-to-mathjax-and-latex-expression,作者为:Ryan Zhao
由于源链接早已无法访问,故备份至此,原版可在Web Archive中找到存档,如有侵权,请联系删除。

本文格式已校对,与原文完全一致

本文从math.stackexchange.com上名为MathJax basic tutorial and quick reference的问题翻译而来,并有所改动。主要讲述了如何使用MathJax和相关的Latex语法。

MathJax简介

MathJax是一款运行在浏览器中的开源的数学符号渲染引擎,使用MathJax可以方便的在浏览器中显示数学公式,不需要使用图片。目前,MathJax可以解析Latex、MathML和ASCIIMathML的标记语言。 MathJax项目于2009年开始,发起人有American Mathematical Society, Design Science等,还有众多的支持者,个人感觉MathJax会成为今后数学符号渲染引擎中的主流,也许现在已经是了。 本文接下来会讲述MathJax的基础用法,但不涉及MathJax的安装及配置。此外,推荐使用StackEdit学习MathJax的语法,它支持Markdown和MathJax,本文使用此编辑器撰写。

基础

公式标记与查看公式

使用MathJax时,需要用一些适当的标记告诉MathJax某段文本是公式代码。此外,MathJax中的公式排版有两种方式,inline和displayed。inline表示公式嵌入到文本段中,displayed表示公式独自成为一个段落。例如,$f(x)=3×x$这是一个inline公式,而下面$$f(x)=3 \times x$$是一个displayed公式。

在MathJax中,默认的displayed公式分隔符有$$...$$\[…\],而默认的inline公式分隔符为 (…) ,当然这些都是可以自定义的,具体配置请参考文档。下文中,使用$$…$$作为displayed分隔符,$…$作为inline分隔符。

此外,可以在渲染完成的公式上方右键点击,唤出右键菜单。在菜单中提供了查看公式代码、设置显示效果和渲染模式的选项。

希腊字母

请参见下表:

名称大写Tex小写Tex
alphaAAα\alpha
betaBBβ\beta
gammaΓ\Gammaγ\gamma
deltaΔ\Deltaδ\delta
epsilonEEϵ\epsilon
zetaZZζ\zeta
etaHHη\eta
thetaΘ\Thetaθ\theta
iotaIIι\iota
kappaKKκ\kappa
lambdaΛ\Lambdaλ\lambda
muMMμ\mu
nuNNν\nu
xiΞXiξ\xi
omicronOOο\omicron
piΠ\Piπ\pi
rhoPPρ\rho
sigmaΣ\Sigmaσ\sigma
tauTTτ\tau
upsilonΥ\Upsilonυ\upsilon
phiΦ\Phiϕ\phi
chiXXχ\chi
psiΨ\Psiψ\psi
omegaΩ\Omegaω\omega

上标与下标

上标和下标分别使用^与_,例如 x_i^2:$x_i^2$。默认情况下,上下标符号仅仅对下一个组起作用。一个组即单个字符或者使用{...}包裹起来的内容。也就是说,如果使用10^10,会得到$10^10$,而10^{10}才是$10^{10}$。同时,大括号还能消除二义性,如x^5^6将得到一个错误,必须使用大括号来界定^的结合性,如{x^5}^6:${x^5}^6$ 或者 x^{5^6}:$x^{5^6}$。

括号

  1. 小括号与方括号:使用原始的( ),[ ]即可,如(2+3)[4+4]:$(2+3)[4+4]$
  2. 大括号:时由于大括号{}被用

来分组,因此需要使用\{和\}表示大括号,也可以使用\lbrace 和\rbrace来表示。如\{a*b\}:$\{a*b\}$,\lbrace a*b \rbrace:$\lbrace a*b \rbrace$。

  1. 尖括号:使用\langle\rangle表示左尖括号和右尖括号。如\langle x \rangle:$\langle x \rangle$。
  2. 上取整:使用\lceil\rceil表示。 如,\lceil x \rceil:$\lceil x \rceil$。
  3. 下取整:使用\lfloor\rfloor表示。如,\lfloor x \rfloor:$\lfloor x \rfloor$。
  4. 不可见括号:使用.表示。

需要注意的是,原始符号并不会随着公式大小缩放。如,(frac12):$(\frac12)$。可以使用left(…right)来自适应的调整括号大小。如下,\lbrace\sum_{i=0}^n i^2 = \frac{(n^2+n)(2n+1)}{6}\rbrace\tag{1.1}:$$\lbrace\sum_{i=0}^n i^2 = \frac{(n^2+n)(2n+1)}{6}\rbrace\tag{1.1}$$
\left \lbrace \sum_{i=0}^n i^2 = \frac{(n^2+n)(2n+1)}{6} \right\rbrace\tag{1.2}:$$\left \lbrace \sum_{i=0}^n i^2 = \frac{(n^2+n)(2n+1)}{6} \right\rbrace\tag{1.2}$$
可以看到,公式1.2中的括号是经过缩放的

求和与积分

\sum用来表示求和符号,其下标表示求和下限,上标表示上限。如,\sum_1^n:$\sum_1^n$。

\int用来表示积分符号,同样地,其上下标表示积分的上下限。如,\int_1^\infty:$\int_1^\infty$。

与此类似的符号还有,\prod:$\prod$,\bigcup:$\bigcup$,\bigcap:$\bigcap$,\iint:$\iint$。

分式与根式

分式的表示。第一种,使用\frac ab,\frac作用于其后的两个组a,b,结果为$\frac ab$。如果你的分子或分母不是单个字符,请使用{..}来分组。第二种,使用\over来分隔一个组的前后两部分,如{a+1\over b+1}:${a+1\over b+1}$。

根式使用\sqrt来表示。如,\sqrt[4]{\frac xy} :$\sqrt[4]{\frac xy} $

字体

  1. 使用\mathbb\Bbb显示黑板粗体字,此字体经常用来表示代表实数、整数、有理数、复数的大写字母。如,$\mathbb{CHNQRZ}$。
  2. 使用\mathbf显示黑体字,如,$\mathbf{ABCDEFGHIJKLMNOPQRSTUVWXYZ}$,$\mathbf{abcdefghijklmnopqrstuvwxyz}$。
  3. 使用\mathtt显示打印机字体,如,$\mathtt{ABCDEFGHIJKLMNOPQRSTUVWXYZ}$,$\mathtt{abcdefghijklmnopqrstuvwxyz}$。
  4. 使用\mathrm显示罗马字体,如,$\mathrm{ABCDEFGHIJKLMNOPQRSTUVWXYZ}$,$\mathrm{abcdefghijklmnopqrstuvwxyz}$。
  5. 使用\mathscr显示手写体,如,$\mathscr{ABCDEFGHIJKLMNOPQRSTUVWXYZ}$。
  6. 使用\mathfrak显示Fraktur字母(一种德国字体),如$\mathfrak{ABCDEFGHIJKLMNOPQRSTUVWXYZ}$,$\mathrm{abcdefghijklmnopqrstuvwxyz}$。

特殊函数与符号

  1. 常见的三角函数,求极限符号可直接使用+缩写即可。如\sin x:$\sin x$,\arctan x:$\arctan x$,\lim_{1\to\infty}:$\lim_{1\to\infty}$。
  2. 比较运算符:\lt \gt \le \ge \neq : $\lt \gt \le \ge \neq$。可以在这些运算符前面加上\not,如\not\lt:$\not\lt$。
  3. \times \div \pm \mp表示:$\times \div \pm \mp$,\cdot表示居中的点,x \cdot y : $x \cdot y$。
  4. 集合关系与运算:\cup \cap \setminus \subset \subseteq \subsetneq \supset \in \notin \emptyset \varnothing :$\cup \cap \setminus \subset \subseteq \subsetneq \supset \in \notin \emptyset \varnothing$.
  5. 表示排列使用{n+1 \choose 2k}\binom{n+1}{2k},${n+1 \choose 2k}$。
  6. 箭头:\to \rightarrow \leftarrow \Rightarrow \Leftarrow \mapsto : $\to \rightarrow \leftarrow \Rightarrow \Leftarrow \mapsto$。
  7. 逻辑运算符:\land \lor \lnot \forall \exists \top \bot \vdash \vDash : $\land \lor \lnot \forall \exists \top \bot \vdash \vDash$。
  8. \star \ast \oplus \circ \bullet : $\star \ast \oplus \circ \bullet$。
  9. \approx \sim \cong \equiv \prec : $\approx \sim \cong \equiv \prec$。
  10. \infty \aleph_0 $\infty \aleph_0$ \nabla \partial $\nabla \partial$ \Im \Re $Im \Re$。
  11. 模运算 \pmode, 如,a\equiv b\pmod n:$a\equiv b\pmod n$。
  12. \ldots\cdots,其区别是dots的位置不同,ldots位置稍低,cdots位置居中。$a_1+a_2+\cdots+a_n$,$a_1, a_2, \ldots ,a_n$。
  13. 一些希腊字母具有变体形式,如 \epsilon \varepsilon : $ \epsilon \varepsilon$, \phi \varphi $\phi \varphi$。

使用Detexify,你可以在网页上画出符号,Detexify会给出相似的符号及其代码。这是一个方便的功能,但是不能保证它给出的符号可以在MathJax中使用,你可以参考supported-latex-commands确定MathJax是否支持此符号。

空间

通常MathJax通过内部策略自己管理公式内部的空间,因此a…ba…….b(.表示空格)都会显示为$ab$。可以通过在ab间加入\,增加些许间隙,\;增加较宽的间隙,\quad\qquad 会增加更大的间隙,如,$a\qquad b$

顶部符号

对于单字符,\hat:$\hat x$,多字符可以使用\widehat,$\widehat {xy}$.类似的还有\hat`,\overline,\vec,\overrightarrow, \dot,\ddot : $\hat x \quad \overline {xyz} \quad \vec a \quad \overrightarrow {x} \quad \dot x \quad \ddot x $。

结束

基础部分就是这些。需要注意的是一些MathJax使用的特殊字符,可以使用转义为原来的含义。如\$表示‘$‘,\_表示下划线。

表格

使用$$\begin{array}{列样式}…\end{array}$$这样的形式来创建表格,列样式可以是clr表示居中,左,右对齐,还可以使用|表示一条竖线。表格中 各行使用\分隔,各列使用&分隔。使用hline在本行前加入一条直线。 例如,

$$
\begin{array}{c|lcr}
n & \text{Left} & \text{Center} & \text{Right} \\
\hline
1 & 0.24 & 1 & 125 \\
2 & -1 & 189 & -8 \\
3 & -20 & 2000 & 1+10i \\
\end{array}
$$

结果:

$$ \begin{array}{c|lcr} n & \text{Left} & \text{Center} & \text{Right} \\ \hline 1 & 0.24 & 1 & 125 \\ 2 & -1 & 189 & -8 \\ 3 & -20 & 2000 & 1+10i \\ \end{array} $$

一个复杂的例子如下:

$$ % outer vertical array of arrays \begin{array}{c} % inner horizontal array of arrays \begin{array}{cc} % inner array of minimum values \begin{array}{c|cccc} \text{min} & 0 & 1 & 2 & 3\\ \hline 0 & 0 & 0 & 0 & 0\\ 1 & 0 & 1 & 1 & 1\\ 2 & 0 & 1 & 2 & 2\\ 3 & 0 & 1 & 2 & 3 \end{array} & % inner array of maximum values \begin{array}{c|cccc} \text{max}& 0& 1& 2& 3\\ \hline 0 & 0 & 1 & 2 & 3\\ 1 & 1 & 1 & 2 & 3\\ 2 & 2 & 2 & 2 & 3\\ 3 & 3 & 3 & 3 & 3 \end{array} \end{array} \\ % inner array of delta values \begin{array}{c|cccc} \Delta& 0& 1& 2& 3\\ \hline 0 & 0 & 1 & 2 & 3\\ 1 & 1 & 0 & 1 & 2\\ 2 & 2 & 1 & 0 & 1\\ 3 & 3 & 2 & 1 & 0 \end{array} \end{array} $$

矩阵

基本用法

使用$$\begin{matrix}…\end{matrix}$$这样的形式来表示矩阵,在\begin与\end之间加入矩阵中的元素即可。矩阵的行之间使用\\分隔,列之间使用&分隔。

例如

$$
        \begin{matrix}
        1 & x & x^2 \\
        1 & y & y^2 \\
        1 & z & z^2 \\
        \end{matrix}
$$

结果:

$$ \begin{matrix} 1 & x & x^2 \\ 1 & y & y^2 \\ 1 & z & z^2 \\ \end{matrix} $$

加括号

如果要对矩阵加括号,可以像上文中提到的一样,使用left与right配合表示括号符号。也可以使用特殊的matrix。即替换\begin{matrix}&hellip;\end{matrix}中的matrix为pmatrix,bmatrix,Bmatrix,vmatrix,Vmatrix.
如pmatrix:$\begin{pmatrix}1& 2\\3& 4\\ \end{pmatrix}$ bmatrix:$\begin{bmatrix}1& 2\\3& 4\\ \end{bmatrix}$ Bmatrix:$\begin{Bmatrix}1& 2\\3& 4\\ \end{Bmatrix}$ vmatrix:$\begin{vmatrix}1& 2\\3& 4\\ \end{vmatrix}$ Vmatrix:$\begin{Vmatrix}1& 2\\3& 4\\ \end{Vmatrix}$

省略元素

可以使用\cdots:$\cdots$ \ddots:$\ddots$ \vdots:$\vdots$来省略矩阵中的元素,如:

$$ \begin{pmatrix} 1 & a_1 & a_1^2 & \cdots & a_1^n \\ 1 & a_2 & a_2^2 & \cdots & a_2^n \\ \vdots & \vdots& \vdots & \ddots & \vdots \\ 1 & a_m & a_m^2 & \cdots & a_m^n \end{pmatrix} $$

增广矩阵

增广矩阵需要使用前面的array来实现,如

$$ \left[
      \begin{array}{cc|c}
        1&2&3\\
        4&5&6
      \end{array}
    \right]
$$

结果:

$$ \left[ \begin{array}{cc|c} 1&2&3\\ 4&5&6 \end{array} \right] $$

对齐的公式

有时候可能需要一系列的公式中等号对齐,如:

$$ \begin{align} \sqrt{37} & = \sqrt{\frac{73^2-1}{12^2}} \\ & = \sqrt{\frac{73^2}{12^2}\cdot\frac{73^2-1}{73^2}} \\ & = \sqrt{\frac{73^2}{12^2}}\sqrt{\frac{73^2-1}{73^2}} \\ & = \frac{73}{12}\sqrt{1 - \frac{1}{73^2}} \\ & \approx \frac{73}{12}\left(1 - \frac{1}{2\cdot73^2}\right) \end{align} $$

这需要使用形如\begin{align}…\end{align}的格式,其中需要使用&来指示需要对齐的位置。请使用右键查看上述公式的代码。

分类表达式

定义函数的时候经常需要分情况给出表达式,可使用\begin{cases}…\end{cases}。其中,使用来分类,使用&指示需要对齐的位置。如:

$$ f(n) = \begin{cases} n/2, & \text{if $n$ is even} \\ 3n+1, & \text{if $n$ is odd} \\ \end{cases} $$

上述公式的括号也可以移动到右侧,不过需要使用array来实现,如下:

$$ \left. \begin{array}{l} \text{if $n$ is even:}&n;/2\\ \text{if $n$ is odd:}&3n+1 \end{array} \right\} =f(n) $$

最后,如果想分类之间的垂直间隔变大,可以使用\[2ex]代替\来分隔不同的情况。(3ex,4ex也可以用,1ex相当于原始距离)。

数学符号查询

一般而言,从一个巨大的符号表中查询所需要的特定符号是一件令人沮丧的事情。在此向大家介绍一个$\LaTeX$手写符号识别系统,如下图:
ScK3R.png

尽情享用吧~ Detexify²

空间问题

在使用Latex公式时,有一些不会影响公式正确性,但却会使其看上去很槽糕的问题。

不要在再指数或者积分中使用 \frac

在指数或者积分表达式中使用\frac会使表达式看起来不清晰,因此在专业的数学排版中很少被使用。应该使用一个水平的/来代替,效果如下:

$$ \begin{array}{cc} \mathrm{Bad} & \mathrm{Better} \\ \hline \\ e^{i\frac{\pi}2} \quad e^{\frac{i\pi}2}& e^{i\pi/2} \\ \int_{-\frac\pi2}^\frac\pi2 \sin x\,dx & \int_{-\pi/2}^{\pi/2}\sin x\,dx \\ \end{array} $$

使用 \mid 代替 | 作为分隔符

符号|作为分隔符时有排版空间大小的问题,应该使用\mid代替。效果如下:

$$ \begin{array}{cc} \mathrm{Bad} & \mathrm{Better} \\ \hline \\ \{x|x^2\in\Bbb Z\} & \{x\mid x^2\in\Bbb Z\} \\ \end{array} $$

多重积分

对于多重积分,不要使用\int\int此类的表达,应该使用\iint \iiint等特殊形式。效果如下:

$$ \begin{array}{cc} \mathrm{Bad} & \mathrm{Better} \\ \hline \\ \int\int_S f(x)\,dy\,dx & \iint_S f(x)\,dy\,dx \\ \int\int\int_V f(x)\,dz\,dy\,dx & \iiint_V f(x)\,dz\,dy\,dx \end{array} $$

此外,在微分前应该使用\,来增加些许空间,否则$\TeX$会将微分紧凑地排列在一起。如下:

$$ \begin{array}{cc} \mathrm{Bad} & \mathrm{Better} \\ \hline \\ \iiint_V f(x)dz dy dx & \iiint_V f(x)\,dz\,dy\,dx \end{array} $$

连分数

书写连分数表达式时,请使用\cfrac代替\frac或者\over两者效果对比如下:

$$ x = a_0 + \cfrac{1^2}{a_1 + \cfrac{2^2}{a_2 + \cfrac{3^2}{a_3 + \cfrac{4^4}{a_4 + \cdots}}}} \tag{\cfrac} $$

$$ x = a_0 + \frac{1^2}{a_1 + \frac{2^2}{a_2 + \frac{3^2}{a_3 + \frac{4^4}{a_4 + \cdots}}}} \tag{\frac} $$

方程组

使用\begin{array} ... \end{array}\left{…\right.配合,表示方程组,如:

$$ \left\{ \begin{array}{c} a_1x+b_1y+c_1z=d_1 \\ a_2x+b_2y+c_2z=d_2 \\ a_3x+b_3y+c_3z=d_3 \end{array} \right. $$

同时,还可以使用\begin{cases}…\end{cases}表达同样的方程组,如:

$$ \begin{cases} a_1x+b_1y+c_1z=d_1 \\ a_2x+b_2y+c_2z=d_2 \\ a_3x+b_3y+c_3z=d_3 \end{cases} $$

对齐方程组中的 = 号,可以使用 \being{aligned} .. \end{aligned},如:

$$ \left\{ \begin{aligned} a_1x+b_1y+c_1z & =d_1+e_1 \\ a_2x+b_2y& =d_2 \\ a_3x+b_3y+c_3z & =d_3 \end{aligned} \right. $$

如果要对齐 = 号 和项,可以使用\being{array}{列样式} .. \end{array},如:

$$ \left\{ \begin{array}{ll} a_1x+b_1y+c_1z & =d_1+e_1 \\ a_2x+b_2y & =d_2 \\ a_3x+b_3y+c_3z & =d_3 \end{array} \right. $$

颜色

命名颜色是浏览器相关的,如果浏览器没有定义相关的颜色名称,则相关文本将被渲染为黑色。以下颜色是HTML4与CSS2标准中定义的一些颜色,其应该被大多数浏览器定义了。

$$ \begin{array}{|rc|} \hline \verb+\color{black}{text}+ & \color{black}{text} \\ \verb+\color{gray}{text}+ & \color{gray}{text} \\ \verb+\color{silver}{text}+ & \color{silver}{text} \\ \verb+\color{white}{text}+ & \color{white}{text} \\ \hline \verb+\color{maroon}{text}+ & \color{maroon}{text} \\ \verb+\color{red}{text}+ & \color{red}{text} \\ \verb+\color{yellow}{text}+ & \color{yellow}{text} \\ \verb+\color{lime}{text}+ & \color{lime}{text} \\ \verb+\color{olive}{text}+ & \color{olive}{text} \\ \verb+\color{green}{text}+ & \color{green}{text} \\ \verb+\color{teal}{text}+ & \color{teal}{text} \\ \verb+\color{aqua}{text}+ & \color{aqua}{text} \\ \verb+\color{blue}{text}+ & \color{blue}{text} \\ \verb+\color{navy}{text}+ & \color{navy}{text} \\ \verb+\color{purple}{text}+ & \color{purple}{text} \\ \verb+\color{fuchsia}{text}+ & \color{magenta}{text} \\ \hline \end{array} $$

此外,HTML5与CSS3也定义了一些颜色名称,参见。同时,颜色也可以使用#rgb的形式来表示,r、g、b分别表示代表颜色值得16进制数,如:

$$ \begin{array}{|rrrrrrrr|}\hline \verb+#000+ & \color{#000}{text} & & & \verb+#00F+ & \color{#00F}{text} & & \\ & & \verb+#0F0+ & \color{#0F0}{text} & & & \verb+#0FF+ & \color{#0FF}{text}\\ \verb+#F00+ & \color{#F00}{text} & & & \verb+#F0F+ & \color{#F0F}{text} & & \\ & & \verb+#FF0+ & \color{#FF0}{text} & & & \verb+#FFF+ & \color{#FFF}{text}\\ \hline \end{array} $$

HTML色彩快速参考手册

公式标记与引用

使用\tag{yourtag}来标记公式,如果想在之后引用该公式,则还需要加上\label{yourlabel}\tag之后,如:

$$ a := x^2-y^3 \tag{*}\label{*} $$

为了引用公式,可以使用\eqref{rlabel},如:

$$a+y^3 \stackrel{\eqref{*}}= x^2$$

可以看到,通过超链接可以跳转到被引用公式位置。

Written with StackEdit.

本文章原载于:http://mlworks.cn/posts/introduction-to-mathjax-and-latex-expression,作者为:Ryan Zhao
由于源链接早已无法访问,故备份至此,原版可在Web Archive中找到存档,如有侵权,请联系删除

]]>
0 https://www.b612.me/code/162.html#comments https://www.b612.me/feed/code/162.html
夏日随想 https://www.b612.me/diary/136.html https://www.b612.me/diary/136.html Fri, 23 Aug 2019 22:09:00 +0800 admin

南方的夏天过的总是很慢,慢到令人生厌。
小时候在家,却总是盼望着夏天,那个时候,夏天意味着雪糕、西瓜、风扇、以及洗澡后的空调房。夏天昼长,也总能在外面多玩一会儿。此外,夏天也是有味道的,一提到夏天,脑海中便总会漂浮着six god的清香味......
现如今,在南方的异乡之中,夏天也仅仅是夏天而已了,湿热的空气让人感到轻微的窒息,急燥的蝉鸣让人烦心......

]]>
0 https://www.b612.me/diary/136.html#comments https://www.b612.me/feed/diary/136.html
Mastodon中彻底删除某账号的解决方法 https://www.b612.me/default/123.html https://www.b612.me/default/123.html Tue, 25 Jun 2019 08:51:00 +0800 admin Mastodon默认没有注册验证码功能,所以如果开放注册的话就会有很多SPAM账号前来骚扰,看着这些占用用户名还一言不发的没头像的spam账号真的很烦,虽然可以从管理界面里封禁,但是看着这些账号的存在就让人很强迫…………故从数据库里删除还是最方便的,这样还能释放被占用的用户名。
当然这种方法最好只用于这些未发言的没在其他实例中出现的spam账号,普通账号的话释放用户名还是会造成歧义的吧(而且在其他示例也有信息存在了

首先进入服务器,使用官方提供的方法设置账号为ban状态,此状态会删除账户所有的资料、所发的toot,一定要三思。。

#非docker执行
RAILS_ENV=production bundle exec bin/tootctl accounts delete [USERNAME]

#docker执行
docker-compose run --rm web bin/tootctl accounts delete [USERNAME]

之后进入Pg数据库

#非docker执行
psql
#docker执行
docker ps
#从上述命令查找到pg所在的id
docker exec -it [id] /bin/bash -c "su - postgres"
psql

之后从web管理界面找到用户的id,如https://xxx.xxx/admin/accounts/13413,id为13413

#删除前最好确认下账户,以防删错
select id,username,domain from accounts where id='[id]';
#执行删除操作
delete from accounts where id='[id]';

当然删除前备份下数据库也是极好的。。。

]]>
0 https://www.b612.me/default/123.html#comments https://www.b612.me/feed/default/123.html