00.00 Contents

今天开始按照JD编号记录博客,并以此同时整理我的知识笔记。

JD编号系统

Johnny.Decimal介绍

简单来说,使用四位数字索引一个条目,这个条目可以是文件、文章甚至是物品。

四位数的前两位代表Area和Category,后两位代表ID。例如我可以使用1代表工作,11代表工作的项目文件,02代表A项目,则我的A项目编号即为10.02

因此一个区域可以有10个分类,每个分类可以有100个条目。另外提及,0编号用来作为特殊用途,例如记录系统整理的相关信息。此篇文章就使用了00.00编号,作为整个系统的目录。

我的JD编号系统

Blog结构

我最近发现使用统一编号的好处是可以将不同工具上的记录整合,例如OneNote、Zotero、文件系统和博客等,因此重新开始整理编号系统。

持续更新中……

韩国签证申请事项

上周申请了韩国签证,记录一下注意事项。

准备

  • 背景:两大一小,父亲和孩子是上海户口,母亲是安徽户口
  • 目标:上海户口十年签
  • 方式:个人递交,母亲代办
  • 材料,材料模板可以从公众号“大韩民国签证申请中心上海中心”下载,需注意所有打印/复印材料使用A4单面,不拼版
    1. 签证申请表,在线填写后下载PDF打印
      • 需提前准备护照首页照片,用于自动识别信息,尽量拍平整无反光以识别正确
      • 下载后不要清除重填,关闭弹窗,信息会保留,重复信息不用重新填写了。因此最好每人单独打开一个网页,如果有错误不用反复重填,只需要修改错误项
      • 实际上写错了到窗口也可以涂改,所以不用一直改
      • 未成年人注意家长代签,如:张子 张父母(代签)
    2. 个人信息同意书,勾选和签名
    3. 代办委托书,需注意有上海户口委托和一般委托两种模板
    4. 小两寸照片,彩色白底,头顶到下巴3.2cm,1张贴在申请表,这里多的也带上了
    5. 每人身份证和复印件
    6. 户口本和整本复印件,这里父子同一户口,母亲另一户口,需要注意整本复印,即使其他非申请人也要
    7. 夫妻双方结婚证和复印件,这里结婚证有两本的,持证人不一样
    8. 出生证和复印件
    9. 每人护照和首页复印件
    10. 微信或支付宝缴费,不能用信用卡,每人750元,如快递再加40元,同一地址只需付一次快递费
    11. 这里准备了学历备案,但没用上

办理流程

  1. 官网预约,周一开始预约接下来两周,也可注意不定时有取消释放的。
  2. 上海长宁区尚嘉的签证中心,门口会检查材料,没问题后可以取号
    • 这里是签证中心,不是使馆,不用担心语言问题
    • 这里被告知母亲安徽户口不能一起申请,要么走自己的申请条件(芝麻信用或白金卡,但都容易拒),要么等父亲的签证通过后再来申请随签
  3. 叫到号交材料交钱即可
  4. 查询进度,窗口有通知查询方式

上海幼升小极简流程

背景

  • 孩子上海户口
  • 房产在浦东新区其他街道,想入学租房所在街道
  • 非梯队学校

流程

  1. 报名前1年内准备人户分离凭证(例如26年4月报名,则需要在25年4月之后)
    1. 租房时和房东确认名额可用,需要备案。(房东可能担心交税,表明可以承担)
    2. 约房东去社区事务受理中心办理租赁备案(也可以随身办线上办,但不如社区方便)
      • 需要材料:身份证,租房合同,房产证
    3. 办好租赁备案同时办人户分离(盖章)
      • 需要材料:身份证,关系证明(出生证或户口本)
  2. 市政策(通常3月底发布),告知报名系统平台等,不重要
  3. 发布区政策和招生细则(市政策发布后约1周),告知报名条件和材料,入学流程
    • 发布信息登记表空表
  4. 校园开放日(通常区政策发布后周末),学校电话联系
    • 和学校老师进一步确认材料细节,登记表发邮件还是现场交
  5. 根据招生细则准备材料
    1. 打印空表并填写
    2. 户口,房产证,出生证,人户分离凭证,原件和复印件
  6. 信息登记(4月中旬)
    • 到学校交材料,收到确认短信即完成
  7. 报名(5月中旬)
    • 使用登记表填写的联系人手机号登陆随申办
    • 报名只有选择是公办还是民办,且选择后不可修改
  8. 学校验证
    • 报名结束后收到短信,告知将在哪个学校验证
    • 材料无问题则不需要做什么事,有问题会通过电话联系补充材料
  9. 发入学告知信息
  10. 发入学通知书

信用卡简明指南

为什么使用信用卡?

银行卡分为借记卡(debit card)和信用卡(credit card)。借记卡是用来存钱的,存多少钱才能花多少钱。信用卡是用来花钱的,花多少钱到时间还多少钱。使用信用卡时银行向商家收取手续费,银行为了拉拢用户给返利,而商家必然增加该成本到售价。反过来想,不使用信用卡的用户也被迫支出了手续费。所以当消费较高时,就考虑使用信用卡了。
使用信用卡的好处:消费和储蓄分开,账单统一,相当于有一笔用于临时周转的备用金,银行赠送的权益。
使用信用卡的坏处:难以量入为出,超前消费,被培养更高的消费习惯。
什么时候适合用信用卡:消费习惯固定,能控制消费欲,有记账习惯,需要报销,出差较多。

信用卡基本介绍

虽然是通过银行发行的,但信用卡的发行方是几大卡组织,常见的有:VISA、MasterCard(万事达卡)、American Express(美国运通)、UnionPay(银联)、JCB。

  • VISA:美国发行,用的地区最多,境外最常用
  • MasterCard:美国发行,境外常用
  • AE:美国发行,境外商旅权益多
  • 银联:中国发行,境外支持的也越来越多,亚洲大部分都能用
  • JCB:日本发行,国内用的少

信用卡有年费和等级。越高级的卡享受的权益越多,当然年费也越高,低级的卡可以通过消费几次来免年费,当然也没什么好的权益。不同卡组织的等级划分和名称不同,大概可以分为普卡、金卡、白金卡(小白金和大白金)、黑金卡。

  • 普卡和金卡:基本一样,属于入门卡,一般每年刷6笔免年费,基本只能参加一些消费优惠或返现活动,额度最高到5万
  • 小白金:需要审核资质,一般每年消费几万免年费,可以搭配积分兑换一些高价值权益如贵宾厅,但性价比较低
  • 大白金:需要有一定资产后才给邀请,一般是几百到小几千刚性年费(不可减免),给固定次数的高价值权益。大白金开始才是真正的高端卡。
  • 黑金:一般是过万的刚性年费,部分权益无限次,适用人群主要是大老板(缩写dlb)

银行为了拉拢信用卡用户会给不同的权益(称作薅羊毛),并降低办卡门槛(称作放水),当然放水的同时权益也随之缩水(称作温暖)。若为了高价值权益而办高等级卡,可能年费会超过使用到的权益价值(称作被反薅)。

  • 新客礼:在该银行没办过信用卡,会给小几百的礼品或免首年年费。
  • 开卡礼:第一次办某个信用卡,一般是高等级卡,根据等级会给几百到上千价值的礼品。
  • 积分:使用信用卡消费可以累积积分,积分可以换购东西、换里程(用于换机票)、换酒店积分(用于换住宿)。对于低端卡积分主要用来换日常消耗品(如奶茶、影音会员等),高端卡积分才变得有价值,可以换机票和住宿。
  • 消费返现:支出时直接优惠或返现、还款时减免或返现、境外消费返现等,日常优惠在消费金额的万分之几到千分之几。
  • 周期权益:一般是高端卡给每年固定次数的优惠住宿、贵宾厅、接送机、挂号陪诊等权益,通常是日常不太用的。

信用卡极简攻略

升级攻略:

  1. 记账,培养稳定的消费习惯
  2. 办金卡,薅新客礼,日常消费优惠和积分兑换的小羊毛
  3. 收入和消费上升后,办小白金卡,薅开卡礼和小羊毛,开始考虑境外消费和卡组织权益
  4. 工作差旅(飞机和境外)多能用回来权益,或等银行放水时办大白金卡,薅开卡礼和贵宾厅。这步由于有了刚性年费,一定要慎重计算真正能使用到的权益价值,避免被反薅。
  5. 在成为大老板前不考虑办黑金卡。

(用过的)银行和卡权益:

  • 招行:单笔消费每满20积1分(其他行都是1元积1分),大白金前的权益基本没有价值
  • 交行:主要是日常消费小羊毛,没什么大的权益
  • 农行:门槛较低,可以参与5倍积分活动,主攻中
  • 运通:常见百夫长卡,贵宾厅和酒店权益多多,尤其是境外
  • 万事达:境内境外一卡通用,购物权益
  • 银联:云闪付消费权益多

嵌入式开发设计模式——ForEach

问题

多个相同的实例对象,其中一部分需要执行某个相同操作。例如有4路天线(使用tx代替),在不同应用中可能选择其中某几路天线,执行“上电-发射-下电”的操作序列。

解决方案

在面向对象的语言中可以实例化多个对象,对需要执行操作的对象分别调用其方法即可。但是在面向过程的C语言中,首先很容易想到的是定义不同的操作函数,将操作哪几个对象作为参数传递。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
typedef enum {
TX_CH_1,
TX_CH_2,
TX_CH_3
} tx_channel_t;

void power_on_action(tx_channel_t tx) {
switch (tx) {
case TX_CH_1: /* do actions for tx1 */ break;
case TX_CH_2: /* do actions for tx2 */ break;
case TX_CH_3: /* do actions for tx3 */ break;
}
}

void tx_power_on(bool tx1, bool tx2, bool tx3) {
if (tx1) {
power_on_action(TX_CH_1);
}
if (tx2) {
power_on_action(TX_CH_2);
}
if (tx3) {
power_on_action(TX_CH_3);
}
}

当对象少于4个时,这种方式很直接高效,但是当对象多于4个时就存在大量重复代码,并且函数参数过长,需要重构设计了。
考虑到某个对象的参数只需要Yes/No两种值,可以想到使用1 bit代表一个对象。如此一个Byte即可表示8个对象。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
void power_on(uint8_t tx_mask) {
for (uint8_t i = 0; i < 8; i++) {
uint8_t sel = 1 << i;
if (0 != (tx_mask & sel)) {
power_on_action(i);
}
}
}

void power_off(uint8_t tx_mask) {
for (uint8_t i = 0; i < 8; i++) {
uint8_t sel = 1 << i;
if (0 != (tx_mask & sel)) {
power_off_action(i);
}
}
}

void send(uint8_t tx_mask) {
for (uint8_t i = 0; i < 8; i++) {
uint8_t sel = 1 << i;
if (0 != (tx_mask & sel)) {
send_action(i);
}
}
}

观察操作函数结构均相同,再进一步重构,将重复的结构抽出来,将操作转为参数。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
static inline void for_each_tx(uint8_t mask, void (*action)(tx_channel_t tx)) {
for (uint8_t i = 0; i < 8; i++) {
if (0 != (tx_mask & (1 << i))) {
action(i);
}
}
}

void power_on(uint8_t tx_mask) {
for_each_tx(tx_mask, power_on_action);
}

void power_off(uint8_t tx_mask) {
for_each_tx(tx_mask, power_off_action);
}

void send(uint8_t tx_mask) {
for_each_tx(tx_mask, send_action);
}

回顾此设计模式,核心原则仍是DRY(Don’t Repeat Yourself),只不过在这里Repeat的不仅是操作,还包括代码结构。

跟风40问,回顾2025

跟风回顾2025年的40个问题

  1. 你今年做了哪些之前从未做过的事?
    • 髌骨骨折手术康复
    • 最长的出差:3周,还顺便第一次去香港
    • 最远的自驾:上海到桐庐
    • 第一次出国:邮轮到日本
  2. 你有没有遵守年初时和自己许下的约定?
    • 年度计划未全部完成
  3. 你身边有人生孩子了吗?
    • 同事
  4. 你身边有人去世了吗?
    • 老板
  5. 你去了哪些城市/州/国家?
    • 国内:南通,苏州,桐庐
    • 境外:香港,长崎,鹿儿岛
  6. 明年你想要获得哪些你今年没有的东西?
    • 物质:已经无欲无求了
    • 技能:践行高效能,提高第2象限
  7. 今年的哪个或哪些日子会铭刻在你的记忆中,为什么?
    • 达不到铭刻的程度但深刻的:桐庐参观溶洞,感叹造物主的创造
  8. 你今年最大的成就是什么?
    • 工作:涨薪了
    • 生活:胃炎几乎好了
    • 信仰:儿主开始上手
  9. 你今年最大的失败是什么?
    • 换工作未成
  10. 你今年还遇到过哪些困难?
    • 工作难以推进,副业又没时间搞
  11. 你今年是否生过病或受过伤?
    • 骨折后增重,坚持每天1g维C,抵抗力提高很多
  12. 你今年买过的最好的东西是什么?
    • 天空见的大路灯
  13. 谁的行为值得去表扬?
    • 没印象
  14. 谁的行为令你感到震惊?
    • 没印象
  15. 你大部分的钱都花到哪里去了?
    • 25% 吃饭和日常购物
    • 21% 保险
    • 16% 房租
    • 11% 节日
  16. 有什么事让你感到超级、超级、超级兴奋?
    • 放假
  17. 哪首歌会永远让你想起这一年?
    • 天上的家。除了祂没有什么能安慰人心的
  18. 与去年的这个时候相比,你是:感到更快乐还是更悲伤了?变得更瘦还是更胖了?变得更富还是更穷了?
    • 更胖了,更轻松了
  19. 你希望自己能做得更多的是什么?
    • 服侍
  20. 你希望自己能做得更少的是什么?
    • 工作
  21. 你是如何度过节假日的?
    • 旅游
  22. 你今年坠入爱河了吗?
    • 备孕二胎
  23. 你是否有讨厌某个你去年此时不觉得讨厌的人呢?
  24. 你最喜欢的电视节目是什么?
  25. 你读过最好的一本书是什么?
    • 重读了《6A的力量》
  26. 你今年发现的最好听的一首歌是什么?
    • 花尽一生来爱你
    • 永活盼望
  27. 你今年看过最喜欢的一部电影是什么?
    • 没记得今年有看电影
  28. 你今年吃过最好吃的一顿饭是什么?
    • 好吃的不是食物本身,而是在哪里和谁吃
    • 小组聚会爱宴
  29. 有什么是你想要且得到了的?
    • 华硕二合一平板电脑
  30. 有什么是你想要却没有得到的?
    • 汉王N10
  31. 你生日那天做了什么?
    • 上班
  32. 有什么还未发生的事,如果发生了,会让你的这一年变得无比满足?
    • 离职领大礼包
  33. 你会如何描述你今年的个人时尚风格?
    • 稳定
  34. 是什么让你保持理智?
    • 信仰
  35. 你最欣赏哪个名人/公众人物?
    • 爱画画的子衿
  36. 哪个政治问题最令你有感而发?
    • 中美博弈吧
  37. 你想念哪些人?
    • 周浦小组
  38. 在你新认识的人之中,谁是最好的?
    • 没有最好
  39. 今年你学到了什么宝贵的人生经验?
    • 知彼解己,合作共赢
  40. 能够总结你这一年的一句话是什么?
    • 在祂手中有平安

嵌入式开发设计模式——状态机

状态机应该是最常用的设计模式了,而且在各种开发语言中,,甚至是硬件描述语言都常用。

状态机简单概念

状态机非常简单和直观,有两个基本概念:

  1. 状态(State):一个对象在某个时刻或某段时间,具有某种稳定的属性,就称其在某个状态。例如灯有“亮”、“灭”两种状态,门有“开”、“关”两种状态等。
  2. 迁移(Transition):从一种状态变到另一种状态就叫迁移。例如灯从亮到灭、从灭到亮,门从开到关、从关到开。

把状态和迁移画出来就成了状态图。从上面的例子也可以想到,有时迁移不会自动发生,例如门从关到开(也就是开门)是因为发生了“要出门”这个条件,并且迁移伴随着动作,也就是开门这个动作。

那么就可以画一个简单的状态图,用/前表示发生条件,/后表示动作

PS.这里的重点为了表现状态机的概念,实际问题中条件和动作可能更加复杂,例如需要区分准入条件和准出条件、进入动作和退出动作等。

状态机设计模式

当需要描述的对象或问题存在多种状态以及多种条件判断时,就可以考虑状态机模式了。画出状态图可以非常直观理解其变化。

状态机有横写和竖写两种方式,区别在于考虑的重点是在状态还是迁移上。有时对象是状态多但迁移条件简单,有时是状态少但迁移条件多。根据写出的代码长度就能看出来了,不需要特别区分。

上面门的例子用状态机来实现。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
typedef enum {
OPENED,
CLOSED
} state_t;

state_t door_state;

void door(void) {
switch (door_state) {
case CLOSED:
if (want_out()) {
open_door();
door_state = OPENED;
}
break;
case OPENED:
if (is_out()) {
close_door();
door_state = CLOSED;
}
break;
default:
// error handling
break;
}
}

另一种方式,

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
void want_out(void) {
if (door_state == CLOSED) {
open_door();
door_state = OPENED;
} else {
/* door is open, nothing to do */
}
}

void is_out(void) {
if (door_state == OPENED) {
close_door();
door_state = CLOSED;
} else {
/* door is closed, nothing to do */
}
}

像之前所说的,标准的状态机模式实现可能还包括很多其他条件和动作,但在实践中通常不会每个迁移每个状态都会用到所有的条件和动作,因此只需要记住状态和迁移的概念,在实现中只写用到的部分就可以了。

嵌入式开发设计模式——代理

在面向对象设计模式中,存在代理模式(Proxy Pattern)和委托模式(Delegation Pattern),二者有很大相似性,但在类的实现上存在少许不同。

而在C语言中,由于天生没有类的概念,因此可以认为这两种模式是一样的。其目的都是为了调用方提供一种动态且一致的接口。

不管是代理还是委托,特点都是调用方自己不做事,把要做的事交给代理去做。

问题

某个产品需要两种指令格式,并需要能够随时切换到另一种格式。

通常实现

因为需要软件运行期间动态切换,所以需要实现两种格式的处理函数,并记录当前使用哪种模式。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
int mode = 0;

void cmd_mode_0_proc(char *buf) {
/* Implementation */
}

void cmd_mode_1_proc(char *buf) {
/* Implementation */
}

void cmd_proc(void) {
/* Receive messages to buf */
if (mode == 0) {
cmd_mode_0_proc(buf);
} else {
cmd_mode_1_proc(buf);
}
}

void change_mode(int value) {
mode = value;
}

代理实现

将处理函数封装起来,给调用方统一接口。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
typedef struct {
void (*proc)(char *buf);
} cmd_proxy_t;

cmd_proxy_t proxy;

void cmd_mode_0_proc(char *buf) {
/* Implementation */
}

void cmd_mode_1_proc(char *buf) {
/* Implementation */
}

void change_mode(int value) {
if (value == 0) {
proxy.proc = cmd_mode_0_proc;
} else {
proxy.proc = cmd_mode_1_proc;
}
}

void cmd_proc(void) {
/* Receive messages to buf */
proxy.proc(buf);
}

代理模式的实现将处理函数的选择从调用方移出。对调用方来说,简化了处理流程,只要交给代理去完成即可。而具体应该调用哪种处理流程是由代理决定的。

什么时候用代理模式呢?就是上面它的特点:动态和统一接口。软件需要在运行时动态修改其行为,而对于调用方并不希望关心其行为的变化,就可以交由代理来处理了。

徐汇牙防所-唯一真神

记录这次补牙问诊经历。

背景:

我有颗牙长歪了导致三颗牙呈三角挤在一起,三角中间的夹缝就很难清理。几年前其中一颗牙烂了在徐汇牙防所补过,最近又感觉遇冷热时牙疼。
牙防所的号一直难预约,看了下九院有更早的号,于是下午请假2小时去了九院。

九院:

  1. 初诊:告知医生遇冷热牙疼,想补牙。医生看了牙后说不好补,先拍片看看烂得程度。
  2. 拍片:拍片需要含一个东西在嘴里,似乎是可以只拍单颗牙的。拍片医生问我只登记了一颗牙为啥开了两次,我不清楚但因为有商业保险也没多问就拍吧。
  3. 回诊:医生看片说烂得挺深,位置不好补,只能根管。又问我这颗牙是不是比较碍事,也可以拔牙,但如果要整牙需要先看正畸医生怎么说。不管哪种当天都做不了。于是回去考虑。
  4. 花费:挂号25+拍片30多

徐汇牙防所:

因为第一次在牙防所同一个位置补牙,医生二话没说半小时不到就补完了两颗(还有另一位置),于是打算再去牙防所看看。回去预约了下周牙防所的号,准备再问问是不是只能根管。周五突发奇想(感谢我主)看了下牙防所预约,竟然有周六一早的号,马上预约了。周六6点半出门前往牙防所。

  1. 初诊:医生问有没有进行性加重,用探针(还是钩?)检查后说,这颗牙不用补,补了后刷不到烂得更快,前几年就是补了另一颗现在这颗也烂了。让我回去后用齿间刷沾抗敏感牙膏清洁,保持住没问题。
  2. 花费:挂号18
  3. 体验:牙防所都是年轻的美女医生,实力也很强,考虑的完全不是好不好补,而是更好的治疗方式。

后续:

买了齿间刷和抗敏感牙膏,还有康中医的脱敏素。早晚用牙膏刷牙+冲牙,午餐和晚餐后用牙缝刷沾牙膏刷,不定时涂脱敏素。几天后牙疼缓解了,只要不是太冷就不怎么疼了。

嵌入式开发设计模式——Template

这是一个非常简单的设计模式,只是提供一下在C语言环境的实现方式。

当某种功能或接口需要在不同平台或存在多种实现方式时,就可以使用这种模式。但需要注意的时在一个工程中只使用其中一种实现方式,即在软件运行时不会同时使用多种方式。

  • 多个芯片的驱动使用相同接口
  • 对某个处理的多种算法实现

例如以下实现,使用_h/_c代表.h/.c文件

将需要实现的接口声明及接口的实现要求定义在该头文件中,头文件就成为了一个模板定义。在不同平台实现时按照头文件要求实现相应的函数。

在工程中include同一路径的c header文件,并根据目标平台编译不同的c source文件,即实现对应目标软件。