• 结对编程作业


    开头

    原型设计

    1.设计说明

    • 功能设计:本次原型设计预期的基本功能有图块移动、计时计步数、更换图形查看目标图形等交互模块、排行榜以及个人成绩等。

    • 原型实现第一次进入图片资源加载可能会很慢

    • 原型设计图主要页面


    • 设计流程图:

    • 样式设计理念:考虑到原型的主要内容是华容道,是具有丰富历史内涵与文化底蕴的主题,所以本次原型设计的风格搭配采用的是以古风为主的简约设计。原型中的主要交互文字使用的是篆书,再联系到给的图片素材是以黑色为主要基调的图块,所以背景图打算用灰白搭配的山水网图,让原型整体戴上缕缕墨色。

    2.原型工具

    • 本次项目使用的原型设计工具是Axure Rp。
    • AxureRP 是一个快速原型制作软件,由美国Axure Software Solutions, Inc.公司开发。Axure RP 能让操作它的人快速准确的创建基于Web的网站流程图、原型页面、交互体验设计、标注详细开发说明,并导出Html原型或规格的Word开发文档。
    • 本次原型设计使用版本是8企业版。使用的交互素材是Axure素材库里的移动端开发素材库。

    3.结对的过程

    • 结对过程描述:出作业时刚好坐在一起,一拍即合。虽然两个都是后端开发,但考虑到对方都是有着开发经验的“老咸鱼”,所以结对的也挺顺利的。
    • 结对照片:

    4.遇到的困难及解决方法

    困难描述 解决尝试 是否解决
    1.图块移动问题。起初的图块移动过于敏感,常常随便一移就导致图块乱窜,严重的可能导致多相同图块的bug 改变了图块变化的思路,有原先的拖动移动变化变成点击白块周围的图块进而交换
    2.小程序登录认证问题。登录时长丢失后端给的token,导致提交记录失败。 先是后端解决了证书的问题(无证书无法正常请求接口),后来小程序端也对登录模块进行了修改
    3.样式显示缺失问题。初涉前端,很多样式会莫名其妙不显示。 查阅了很多css、js以及小程序相关博客
    4.上线问题。因为本次原型实现采用的是小程序,小程序的上线存在着诸多问题。 查官方文档,查博客,问客服
    5.审美问题。老直男了,界面设计一直感觉不是很满意,-_-|| 看其他优秀设计 ×

    AI与原型设计实现

    代码实现思路

    网络接口的使用

    • 网络接口用的都是python的requests库

    代码组织

    • 算法框架(算法详细在后面)

    tim503b268bf8b2d840.png

    • 微信小程序后台

    后台使用的是django框架。整个类的使用都是依据django而来的,唯二值得提的是

    1.首先是token的构造,由于没找到类似的库,我是参考JWT构造的token,

    def generate_token(no, key="key", expire=1000000):
        ts_str = str(time.time() + expire)
        ts_byte = ts_str.encode("utf-8")
        sha1_result = hmac.new((key + str(no)).encode("utf-8"), ts_byte, 'sha1').hexdigest()
        token = str(no) + ':' + ts_str + ':' + sha1_result
        b64_token = base64.b64encode(token.encode("utf-8"))
        return b64_token.decode("utf-8")
    
    
    def certify_token(token, key="key"):
        if token is None:
            raise TokenError("没有token")
        try:
            token_str = base64.b64decode(token)
            token_list = token_str.decode('utf-8').split(':')
        except Exception:
            raise TokenError("token解析错误")
        if len(token_list) != 3:
            raise TokenError("token格式错误")
        ts_str = token_list[1]
        if float(ts_str) < time.time():
            # token expired
            raise TokenError("token过期")
        known_sha1 = token_list[2]
        sha1 = hmac.new((key + token_list[0]).encode("utf-8"), ts_str.encode('utf-8'), 'sha1')
        sha_ans = sha1.hexdigest()
        if sha_ans != known_sha1:
            # token certification failed
            raise TokenError("token错误")
            # token certification success
        return str(token_list[0])
    

    然后在view中对需要请求进行token验证与创建

    1. 异常处理

    一个正常的后台必须要对错误的请求返回正确的错误码。错误时,django似乎本身会返回html页面。而我在了解中间件(middleware)后,使用中间件构造了异常处理模块。

    class ExceptionMiddleware(MiddlewareMixin):
    
        def __init__(self, get_response=None):
            super(ExceptionMiddleware, self).__init__(get_response)
    
        @staticmethod
        def process_exception(request, exception):
    
            if isinstance(exception, TokenError):
                return JsonResponse({"result": 401, "msg": exception.value})
    
            if isinstance(exception, NoResultError):
                return JsonResponse({"result": 404, "msg": exception.value})
    
            print("========================================================================")
            print('traceback.format_exc():
    %s' % traceback.format_exc())
    
            return JsonResponse({"result": 500, "msg": "error"})
    

    数字华容道算法/算法的关键

    基本思想是bfs,由于强制交换的存在,我们需要考虑两轮bfs,分别为

    • 在强制交换前进行bfs
    • 在强制交换前无解启用强制交换后进行bfs

    然而还有存在两个问题:

    1. 在强制交换时华容道有哪几种情况?

    首先由于bfs的特性(每一次都是此时最远的一步),强制交换时有的情况一定在之前的bfs中出现过。

    然后在交换前偶数次都可以通过左右横跳(ad)来达到强制交换时存在。

    而由于华容道的特点——他每一步都需要移动而且是上下左右选一。所以如果奇数步白块是在(1,3,5,7,9)中的一个。而偶数步白块是一定是在(2,4,6,8)中的一个。所以交换前奇数步是不可能在交换前出现。

    所以我们只需要把所有交换前偶数次步数的华容道状态存起来。在强制交换时把这些珍藏的状态那来交换作为第二次bfs的初始状态。

    1. 如何确定强制交换后有解

    这个判定方法是判断逆序对的数量(不把空白块计入)是否为偶数个。

    在排序好的华容道上,逆序对是0;

    而空白块的移动有四种情况,wasd,在ad——左右变化的时候,华容道的逆序对不会变

    当进行w或s时

    原来第一列 原来第二列 原来第三列 移动 移后第一列 移后第二列 移后第三列
    a b c ----------------------------> a c
    d f ----------------------------> d b f
    g h i ----------------------------> g h i

    原来的逆序对数为 m + (b,c)+ (b,d)

    移后的逆序对数为 m + (c,d)+ (c,b)

    其中m为前后无变化的逆序对信息

    以此变化量为 delta(逆序对) = (b,c)+ (b,d) - (c,d)- (c,b)

    因为(b,c)与(c,b)只有一个会同时是逆序对,(b,d)与(d,b)也只有一个会同时是逆序对,所以delta(逆序对)为 -2,0,2。因此我们只需要确定是偶数个逆序对有解。

    性能分析与改进

    我一开始是用python写算法,然而python展现的效率。。。

    所以我对python算法进行了改进:

    最早是__Hash__函数,因为已出现的状态存在于字典,而华容道的特点使我们可以构造一种__Hash__算法即

        def __hash__(self):
            t = 0
            for i in range(3):
                for j in range(3):
                    t = t*10 + self.square[i][j]
            return t
    

    但优化后时间仍在30s左右

    pythonProject.png

    接着取消复制类(deepcopy),改为创建新的对象

    pythonProject.png
    pythonProject1_1.png

    结果只能达到10s左右,因此,我更改语言,使用c++(果然写算法用C++才是最舒服),最后能达0.8s的水平。

    接着优化在于我用来存储曾经出现的华容道状态的数组,(因为我开辟了一个1000000000的bool数组)在强制交换后马上需要将其清零。这里占了极大的时间。我先将数组改下十倍(华容道九宫格九个数字只要出现8个就能推出最后一个所以用更小的数组),然后又开辟一个新的数组用于记录华容道交换后的状态。这样一来时间能在单独算法的时间能0.4秒以下。

    关于图像处理,我一开始使用的是PIL的ImageChops.difference,我尝试过将给的base64进行Hash,本想到时候可进行查表直接返回对应的华容道状态。然而我直接拼接的华容道图片终是与接口返回的有差别。用PIL的ImageChops.difference是可判别,但是在文件大小等方面却不一样,导致hash不出相同的值。结果优化一直失败。

    单元测试

    链接

    上面是我写的脚本,作用是用于自动对测试组提供的问题接口来请求,求解,返回,并将结果存取下来。

    用他来判别算法是否正确

    Github的代码签入记录

    算法

    QQ20201019084211.png

    小程序

    QQ20201016194637.png

    困难及解决方法

    • 算法在最开始我遗漏了,交换前有哪些状态这个问题,不过最后还是改回来了

    • django的orm是一个感觉奇怪的玩意。他一定义外键就会变成拉入一个类进来。导致在返回排行榜的时候,会自己返回一个用户。而解决方法,我是靠修改序列化的方法,将返回一个用户改为返回他的头像与名字

    • 另外一个问题是微信小程序需要的https证书与域名,这个https证书依靠阿里云的免费ssl,域名5元一年,真正的问题在于网站备案,由于办事效率的不确定,我最后借用了别人的域名

    评价你的队友

    • 值得学习的地方

      他提供了非常优秀前端界面,对我们的作业提供了许多优秀的建议

    • 需要改进的地方

      还需要加强审美

    结对作业的PSP和学习进度条

    第N周 新增代码(行) 累计代码(行) 本周学习耗时(小时) 累计学习耗时(小时) 重要成长
    1 278 278 12 12 学习了python的PIL,能够对比头像,并实现了算法一部分
    2 385-142 421 13 25 将算法改为c++,算法完全实现 ,学习了django的orm集
    3 272 693 10 35 后台功能加强,实现token,一对一实现,算法修正,测试脚本实现
    4 182 876 8 43 实现Ai大比拼脚本,进行算法优化
    PSP2.1 Personal Software Process Stages 预估耗时(分钟) 实际耗时(分钟)
    Planning 计划 7 6
    · Estimate · 估计这个任务需要多少时间 7 6
    Development 开发 2000 2239
    · Analysis · 需求分析 (包括学习新技术) 450 672
    · Design Spec · 生成设计文档 40 68
    · Design Review · 设计复审 40 62
    · Coding Standard · 代码规范 (为目前的开发制定合适的规范) 0 0
    · Design · 具体设计 20 12
    · Coding · 具体编码 1000 815
    · Code Review · 代码复审 20 58
    · Test · 测试(自我测试,修改代码,提交修改) 430 552
    Reporting 报告 190 317
    · Test Repor · 测试报告 90 235
    · Size Measurement · 计算工作量 40 48
    · Postmortem & Process Improvement Plan · 事后总结, 并提出过程改进计划 60 34
    合计 2197 2562
  • 相关阅读:
    MVAPICH
    sql server触发器的例子
    Sql Server 判断表或数据库是否存在
    JS验证用户真实姓名
    js实现瀑布流的一种简单方法实例分享
    C#实现登录窗口(不用隐藏)
    判断滚动条到底部的JS代码
    php 中文字符串首字母的获取函数
    C#获取当前页面的URL
    C#动态生成图书信息XML文件
  • 原文地址:https://www.cnblogs.com/vcfghch/p/13838541.html
Copyright © 2020-2023  润新知