同学们,我们用了两周时间完成了 TMS 的部分功能,包括注册、登录、打印信息等。在 TMS-2 中,我们将会实现上架商品、购买商品等一系列相关命令。
在开始编码之前,建议大家先仔细阅读需求说明和文末的 HINTS。
编写好的代码需要经过 patpat 评测。通过所有的测试点后,需将整个项目文件打包上传到云平台,即可完成本次实验。希望大家能够认真完成,不作弊不抄袭。
此外再次说明,对于各类导致 WA 和 RE 的逻辑漏洞,助教们在原则上不能为你提供太多帮助,更不能提供测试数据。另一方面,试想每个同学都发一个上百行上千行的项目文件,助教也无从看起。每个测试点都有很多命令,如果助教要面向测试点 debug,也只能一条一条复制粘贴,效率自然非常低下。建议同学们在编码时严谨地考虑各类情况,对于题目表述有不确定的,不妨问问其他同学或直接和助教交流,你的问题很可能被写进 QA 文档,这也为更多同学提供了帮助🤔。
对于每一种“合法情况”,同学们应当认真考虑其反面。例如,“可含前导零的五位整数”,其反面可以是 1234
,可以是 123456
,也可以是 12a34
、_+$%&
等非数字输入,这些都应该考虑到位,不然不仅可能误判,还可能导致参数分隔错误、参数数量不一致、库方法抛异常等更让人摸不着头脑的 bug。另,下文中的“字母”如果不加说明,大小写均可。
patpat 的下载和使用说明请参考:patpat 使用指南。
Stream
与 Collection
很有用)鉴于迭代二很多同学反馈难度较大,我们将截止时间延长至 10 月 30 日 23:59。希望大家能够抓紧时间完成,不要拖到最后一天。
本次迭代需要完成的命令如下
命令符 | 说明 |
---|---|
registerShop 店铺名称 | 注册店铺 |
putCommodity 可选参数 | 上架商品 |
listShop 可选参数 | 查看店铺 |
listCommodity 可选参数 | 查看商品 |
searchCommodity | 查找商品 |
buyCommodity | 购买商品 |
removeCommodity | 下架商品 |
cancelShop | 注销店铺 |
店铺
Merchant
的用户(商家)可以注册店铺,每个商家可注册最多 5 家店铺。对于同一商家,店铺名称不可重复。S-数字
,例如 S-1
,S-2
,数字无前导零。店铺编号是全局的:从 1 开始分配,若当前系统仅有 A、B 两个商家,A商家先注册了 4 家店铺,那么当B商家注册第一家店铺时,其店铺编号分配为 S-5
。特别, S-0
是不合法的。命令符 | 参数1 |
---|---|
registerShop | 店铺名称 |
店铺名称
-
、下划线_
组成。1.2.1 注册店铺成功
1 | Register shop success (shopId: S-X) |
其中X
为店铺编号的数字。
1.2.2 参数数量不合法
1 | Illegal argument count |
1.2.3 未登录
1 | Please log in first |
1.2.4 登录用户身份不是Merchant
1 | Permission denied |
1.2.5 拥有店铺已达最大数量
1 | Shop count reached limit |
1.2.6 店铺名称不合法
1 | Illegal shop name |
1.2.7 店铺名称已存在
1 | Shop name already exists |
(建议阅读 HINTS,理清商家、店铺、商品三者的关系)
商品
Merchant
的用户(商家)可以在店铺中上架商品。C-数字
,数字无前导零,例如 C-1
,C-2
。该编号根据商品上架的顺序获得,从 1 开始。商品编号同样是全局的 。该命令有两种格式:一种为上架新商品,一种为上架已有商品。
上架新商品
命令符 | 参数1 | 参数2 | 参数3 | 参数4 |
---|---|---|---|---|
putCommodity | 店铺编号 | 商品名称 | 商品单价 | 商品数量 |
该命令用于上架一款全新的商品(生成一个新的商品编号)。
店铺编号
商品名称
-
、下划线 _
组成。商品单价
商品数量
商品数量必须大于 0。
商品数量必须为整数,不能有前导零。
对于是数字的参数,测试用例保证参数为数字格式,转换时无需特殊考虑。
上架已有商品命令
命令符 | 参数1 | 参数2 | 参数3 |
---|---|---|---|
putCommodity | 店铺编号 | 商品编号 | 商品数量 |
需满足要求如下
店铺编号
商品编号
商品数量
上架新商品
2.2.1 上架商品成功
1 | Put commodity success (commodityId: C-X) |
其中X
为商品编号的数字。
2.2.2 参数数量不合法
1 | Illegal argument count |
2.2.3 未登录
1 | Please log in first |
2.2.4 登录用户身份不是 Merchant
1 | Permission denied |
2.2.5 店铺编号不合法
1 | Illegal shop id |
2.2.6 店铺未注册、店铺不属于该商家、店铺已注销
1 | Shop id not exists |
2.2.7 商品名称不合法
1 | Illegal commodity name |
2.2.8 商品单价不合法
1 | Illegal commodity price |
2.2.9 商品数量不合法
1 | Illegal commodity quantity |
上架已有商品
2.2.10 上架商品成功
1 | Put commodity success (commodityId: C-X) |
其中X
为商品编号的数字。
2.2.11 参数数量不合法
1 | Illegal argument count |
2.2.12 未登录
1 | Please log in first |
2.2.13 登录用户身份不是 Merchant
1 | Permission denied |
2.2.14 店铺编号不合法
1 | Illegal shop id |
2.2.15 店铺未注册、店铺不属于该商家、店铺已注销
1 | Shop id not exists |
2.2.16 商品编号不合法
1 | Illegal commodity id |
2.2.17 商品编号未注册、商品编号不属于该商家、商品已下架
1 | Commodity id not exists |
2.2.18 商品数量不合法
1 | Illegal commodity quantity |
命令符 | 可选参数 |
---|---|
listShop | [Kakafee 卡号] |
3.2.1 成功打印信息
每家店铺占一行,按店铺编号由小到大输出。
顾客与商家打印格式为 店铺id 店铺名称
1 | # 举例 |
管理员打印格式为 Kakafee卡号 店铺id 店铺名称
1 | # 举例 |
无参数
3.2.2 参数数量不合法
1 | Illegal argument count |
3.2.3 未登录
1 | Please log in first |
3.2.3 店铺不存在
对顾客和管理员而言是当前系统无店铺,对商家而言是名下无店铺。
1 | Shop not exists |
参数为 Kakafee 卡号
3.2.4 参数数量不合法
1 | Illegal argument count |
3.2.5 未登录
1 | Please log in first |
3.2.6 非管理员用户执行有参数的命令
1 | Permission denied |
3.2.7 Kakafee 卡号不合法
1 | Illegal Kakafee number |
3.2.8 Kakafee 卡号对应的用户未注册
1 | Kakafee number not exists |
3.2.9 Kakafee 卡号对应的用户身份不是 Merchant
1 | Kakafee number does not belong to a Merchant |
3.2.10 Kakafee 卡号对应的商家名下无店铺
1 | Shop not exists |
命令符 | 可选参数 |
---|---|
listCommodity | [店铺编号] |
4.2.1 成功打印信息
每件商品占一行,按照 shopId 从小到大输出;对于同一商店的商品,按照 commodityId 从小到大输出。格式为 店铺id: 商品id 商品名称 商品价格 商品数量
,其中,商品价格保留两位小数,单位为 yuan。
提示
库存为 0 的商品也需要打印,不打印该店铺被下架的商品。(但是查找商品时库存为 0 的商品不打印。)
1 | # 举例 |
无参数
4.2.2 参数数量不合法
1 | Illegal argument count |
4.2.3 未登录
1 | Please log in first |
4.2.4 当前系统无商品、商家名下店铺无商品
1 | Commodity not exists |
参数为店铺编号
4.2.5 参数数量不合法
1 | Illegal argument count |
4.2.6 未登录
1 | Please log in first |
4.2.7 店铺编号不合法
1 | Illegal shop id |
4.2.8 店铺不存在
对管理员和顾客而言是店铺未注册或已注销,对商家而言是店铺不属于该商家店、店铺未注册或已注销。
1 | Shop id not exists |
4.2.9 当前店铺无商品
1 | Commodity not exists |
命令符 | 参数1 |
---|---|
searchCommodity | 商品名称 |
5.2.1 查找成功打印信息
每件匹配的商品占一行,按照 shopId 从小到大输出;对于同一商店的商品,按照 commodityId 从小到大输出。格式为店铺id: 商品id 商品名称 商品价格 商品数量
,其中,商品价格保留两位小数,单位为 yuan。
1 | # 举例 |
5.2.2 参数数量不合法
1 | Illegal argument count |
5.2.3 未登录
1 | Please log in first |
5.2.4 商品名称不合法
1 | Illegal commodity name |
5.2.5 商品不存在或商品数量均为零
1 | Commodity not exists |
命令符 | 参数1 | 参数2 | 参数3 |
---|---|---|---|
buyCommodity | 店铺编号 | 商品编号 | 购买数量 |
只有顾客可购买商品,购买后相应店铺的相应商品数量应减少。
购买数量
6.2.1 购买成功
1 | Buy commodity success |
6.2.2 参数数量不合法
1 | Illegal argument count |
6.2.3 未登录
1 | Please log in first |
6.2.4 登录用户身份不是 Customer
1 | Permission denied |
6.2.5 店铺编号不合法
1 | Illegal shop id |
6.2.6 店铺编号不存在
1 | Shop id not exists |
6.2.6 商品编号不合法
1 | Illegal commodity id |
6.2.7 商品编号未注册、该商品不是该店铺的产品
1 | Commodity id not exists |
6.2.8 购买数量不合法、购买数量大于商品数量
1 | Illegal buy quantity |
命令符 | 参数1 | 可选参数 |
---|---|---|
removeCommodity | 商品编号 | [店铺编号] |
提示:
商品最终归属于商家。对于两条下架商品指令,都需要清空库存,它们的区别如下:
当商品在某个店铺下架时,它是店铺的下架商品,仍是商家的上架商品,商家可以在自己的所有店铺上架。
再次在该店铺下架:输出商品不存在。
查看商店商品:不打印该商品(因为该商品已下架)。
当商品在全局下架时,它是店铺的下架商品,同时是商家的下架商品,商家不能再次上架。
无可选参数
7.2.1 下架商品成功
1 | Remove commodity success |
7.2.2 参数数量不合法
1 | Illegal argument count |
7.2.3 未登录
1 | Please log in first |
7.2.4 登录用户身份不是 Merchant
或 Administrator
1 | Permission denied |
7.2.5 商品编号不合法
1 | Illegal commodity id |
7.2.6 商品编号不存在、商品不属于该商家
1 | Commodity id not exists |
可选参数为店铺编号
7.2.7 下架商品成功
1 | Remove commodity success |
7.2.8 参数数量不合法
1 | Illegal argument count |
7.2.9 未登录
1 | Please log in first |
7.2.10 登录用户身份不是 Merchant
或 Administrator
1 | Permission denied |
7.2.11 商品编号不合法
1 | Illegal commodity id |
7.2.12 店铺编号不合法
1 | Illegal shop id |
7.2.13 店铺编号不存在、店铺不属于该商家
1 | Shop id not exists |
7.2.14 商品编号不存在、商品不属于该商家、商品不属于该店铺
1 | Commodity id not exists |
命令符 | 参数1 |
---|---|
cancelShop | 店铺编号 |
8.2.1 注销店铺成功
1 | Cancel shop success |
8.2.2 参数数量不合法
1 | Illegal argument count |
8.2.3 未登录
1 | Please log in first |
8.2.4 登录用户身份不是 Merchant
或 Administrator
1 | Permission denied |
8.2.5 店铺编号不合法
1 | Illegal shop id |
8.2.6 店铺编号不存在
对管理员而言,店铺编号未注册或已注销;对商家而言,店铺编号未注册或已注销或者不属于自己。
1 | Shop id not exists |
商家拥有店铺、店铺中有商品。上架的商品最终归属在商家,上架新商品会给商家添加一种商品,商家可在自己的所有店铺里添加该商品,但商家不可添加其他商家的商品。
同一商家名下的店铺名称不可相同,不同商家的店铺名称可以相同。
所有打印商品、店铺信息的命令,如无特殊说明,均不打印下架商品、注销店铺的信息。
关于两种下架商品命令的区别
注销店铺后,需要下架店铺中的商品。 此处的下架仅下架该店铺中的所有商品,即不改变商品的上架状态。
对于同一命令不同格式,在命令反馈说明中将不同情况均分开进行了说明。实际编写过程中会有一些判断是共通的,大家可以视情况简化重复的代码。
相信大家在阅读完商品相关命令以及提示后,会发现这样一个事情:商品有“数量”这一属性,但是这一属性在具体到某一商店时,与其在某一商家、全局时的值是不同的。也就是商品在全局时的数量等于对应商家商品的数量,而这个数量等于商品在该商家店铺中数量之和。我们可以用下面这种思路来解决。
既然这一属性在不同地方的值不同,那我们干脆让全局与商家处存放的是同一个实例;在店铺中存放另一个实例,只要维护好他们之间的数量关系就可以了。
1 | // Commodity 类 |
通过以上代码,我们可以获取一个全新的商品类的实例。
但其实本系统中并没有要求对于商品数量进行一个全局的统计,那我们不如在全局就干脆不要数量这个属性,只对店铺中的商品保留这个属性,也省去了维护数量关系的麻烦。
相关实体类:
1 | public class CommodityUnit { |
相关静态类:
1 | private static HashMap<String, CommodityUnit> |
这里只是提供一个简单的思路以便参考。实际编写中,商品可能还需要记录所在商店的信息,大家可以视具体情况而定。
通过如上代码的实现,我们可以发现:尽管不同商店均存储着不同的商品实例,但是对于同一种商品,他们的CommodityUnit
属性均为同一个实例。
这也正是享元模式的目的:减少重复对象或提取不同对象的重复属性,以节省空间开销。
在相关资料中给出的链接中的样例,其重点在于减少重复对象,而上述商品的设计重点在于提取不同对象的重复属性。
当然,以本系统的设计而言,商品的享元模式设计并不能实现节省大量空间开销的作用(一个商家最多有 5 间店铺)。但还是希望能够让大家亲自动手,体会一下程序设计模式的作用。
集合排序
1 | // commodities 是一个 HashMap<String, Commodity>,其键为商品 id |
1 | register 000117861001 aaaa adddh7hhh@ adddh7hhh@ Administrator |