选座验证的优化

自从某FFF团把情人节电影院的单号位置电影票全买走之后,电影院发现,不能再这么纵容他们了,于是就给了售票系统验证用户选座的要求。

从老系统重构过来,选座验证逻辑也是下手的好机会,经过优化,效果不错

优化结果

原选座判定

新版选座判定

实现的最终效果是相同的,除却之前提到的Model Class带来的进一步抽象之外,这里还将判断逻辑巧妙的缩减,将分散的座位判断改换为连续的模式验证。

回到出发点

原始代码很复杂,所以需要去找这里的最终逻辑;经过各种沟通,发觉这里的出发点其实很简单:中间不要剩余一个座位。

如果中间只有一个位置,那么情侣就没办法买,只能卖给单身狗了,这怎么可以呢

但是电影厅的座位分布并不是理想化的,而且卖出去的座位分布也可能是各种各样,容易产生各种情况,也导致了原始的判断逻辑异常复杂。

但是经过仔细思考,可以发现这里有很大的简化空间。

逻辑梳理

首先,每次判断只需要对单行来进行,(毕竟这个是为了情侣考虑的,基本上情侣左右相邻,而不会前后相邻而坐),那么就有这么几种情况是不可以的:

  • 刚选的两个座位中间有一个空位
  • 刚选的座位和其他位置中间有一个空位

后者展开为:

  • 刚选的两个座位中间有一个空位
  • 刚选的座位和已售出的座位中间有一个空位
  • 刚选的座位和无座位置(没有椅子的位置)中间有一个空位
  • 刚选的座位和影厅边缘中间有一个空位

其中后边几种可以归纳起来,就会变成:

  • 刚选的两个座位中间有一个空位
  • 刚选的座位和(已售出的座位或无座位置或影厅边缘)中间有一个空位

但是这个第二种情况有特殊情况是可以选择的,即:如果只有两个空位(旁边是已售出的座位或无座位置或影厅边缘),则可以只选其中一个位置。(不然单身童鞋可能面临还有俩位置却买不了票的奇葩情况)

明明剩俩座位却不能只买一张,看个电影也要欺负单身狗,这世界没救了

所以讲上述条件的第二个加上限制,就会变成 以下两种情况是不可以的:

  • 刚选的两个座位中间有一个空位
  • 刚选的座位和(已售出的座位或无座位置或影厅边缘)中间有一个空位,但是另外一边是(已售出的座位或无座位置或影厅边缘)的情况除外

这里可以想到,(已售出的座位或无座位置或影厅边缘)的情况除外,那不就是可选的空座吗?于是就可以转化为:

  • 刚选的两个座位中间有一个空位
  • 刚选的座位和(已售出的座位或无座位置或影厅边缘)中间有一个空位,但是另外一边也必须是可选的空位

转为代码

逻辑整理的差不多了,那么可以开始转化为代码了,如果用一般的思路,大概需要双重循环加上很多个if判断语句,上述的简洁思想就没办法传承到代码中了

这时候,我想到一个很方便的方式,我们这里要做的事情基本上就是pattern recognizing,即模式识别;想到这里,就可以想到作为擅长处理字符串的js有一个内置大杀器,即regex 正则表达式。正则表达式最擅长的就是字符串模式识别、模式套用。

那么想到这里,我们要做的就是把每行的座位先转换成字符串,然后用相应的pattern去套,看是不是能够匹配了。

这里这样去转换:

说明 代码
用户选择的座位: V_SELECT='S'
边缘: V_EDGE='E'
没有座: V_VOID='V'
已经卖出去: V_LOCK='L'
空位: V_AVAILABLE='A'

然后将我们的规则转化为正则表达式:

  • 刚选的两个座位中间有一个空位

    • S+AS+
  • 刚选的座位和(已售出的座位或无座位置或影厅边缘)中间有一个空位,但是另外一边也必须是可选的空位

    • BAS+A+
    • A+S+AB

那么这里的验证选座的代码部分就是这个样子:

有两个循环,一个是循环所有座位行,一个是循环这几个正则表达式,然后每行都会被每个正则表达式所验证,如果验证通过了,说明选座是不合法的,就会在界面提示,阻挡下一部动作。

发表评论

电子邮件地址不会被公开。 必填项已用*标注